Distribution
Detta dokument är ej under kontrollerad distribution.
Innehavaren ansvarar själv för att den senaste utgåvan
av detta dokument används och att inaktuella kopior (utskrifter) förstörs.
Senaste version kan hämtas från Internet i PDF format: |
Revisionshistorik
Revision | Datum | Kommentar |
P1.0.0 | 1999-10-08 | Första allmänt tillgängliga versionen. |
P1.0.1 | 1999-10-14 | Uppdaterade dokumentformatet till Enea Data standard. |
P1.1.0 | 1999-11-01 | Större översyn och uppsnyggning. |
Innehållsförteckning
1 Inledning *
1.1 Bakgrund *
Struktur *
3 Länklager *
3.2 CSLIP *
3.3 PPP *
3.4 Diskussion *
5 Nätverkslagret *
6.2 UDP *
6.3 TCP *
8 Applikationslager *
Det här dokumentet är en specifikation av de protokoll
som ingår i mitt exjobb, som jag gör på Enea Data, Real-Time
Systems. Målet är att implementera en prototyp av en minnessnål
TCP/IP protokollsvit för DSP OS. Jag förklarar vilka protokoll
som ska ingå och varför. De gånger jag gör avsteg
från standarden för protokollen förklarar jag varför
och beskriver vilka effekter avstegen har. Jag beskriver också lite
översiktligt vilka block en implementation förväntas ha
och hur de olika protokollen hänger ihop, samt lite kort om vad som
krävs för att de ska hänga ihop.
Den maskinvara som jag tänker mig är en direkt asynkron seriell 115 kbps förbindelse mellan två värddatorer. En sådan seriell port är standard på alla PC datorer, som därför kommer att kunna användas i andra änden av kabeln. Maskinvaran kan sända och ta emot en byteström som skickas över den seriella förbindelsen.
DSP-OS har inte någon BIOS så drivrutinen måste registrera sig hos anslutningsgränssnittet. Drivrutinen måste själv se till att den går att konfigureras och att den är klar att användas innan den registrerar sig. Så fort drivrutinen är registrerad kan den komma att tas i bruk. Före registreringen vet inte protokollsviten om att drivrutinen finns.
Drivrutinen kommunicerar med länklagret med hjälp av signaler och eftersom drivrutinen kör i två interrupt processer så innebär signaler inte mycket extra arbete.
Ett krav är att drivrutinen ska kunna skriva två buffertar i sekvens så att det ser ut som en buffert på nätverket. Problemet är att protokollhuvuden måste skrivas före bufferten från applikationen. Det finns tre sätt att lösa det på:
Länklagret bildar tillsammans med drivrutinen en anslutning
och tillhandahåller leverans av paket mellan två noder, som
är anslutna till varandra.
För en asynkron seriell förbindelse finns det tre protokoll som är aktuella: SLIP, CSLIP och PPP.
Protokollet har bara ett syfte och det är att markera var
ett paket börjar och slutar i en byteström. Det är inte
alls svårt att göra och därför är SLIP väldigt
enkelt och minnessnålt.
Eftersom vissa tecken byts ut mot två tecken kan ett paket i värsta fall bli dubbelt så stort. Det går att räkna antalet tecken som måste bytas ut och på så sätt räkna ut vilken längd paketet kommer att få efter substitutionen, men det tar lite tid. Enda alternativet är att skapa en dubbelt så stor buffert för att hålla paketet efter substitution.
OSE-delta har inget stöd idag för SLIP, men det är väldigt enkelt att lägga till.
För att förbättra prestandan för SLIP över
långsamma seriella förbindelser skrevs standarden för CSLIP,
som bygger ut SLIP med komprimering av protokollhuvuden av typen TCP och
IP.
Komprimeringen fungerar bara på paket med TCP och IP protokollhuvuden och komprimerar dessa från 40 bytes till 5 bytes, men det är inte alltid möjligt att utföra komprimeringen. För att den ska lyckas krävs det att förändringarna i huvudena på efterföljande paket är små och förutsebara, annars måste protokollhuvudena skickas okomprimerade. Att spara 35 bytes i ett paket på 576 bytes (se IP) över en 115 kbps förbindelse ger 6,1% mindre storlek och sparar 0,3 ms i tid. Men sedan tillkommer en del arbete och minne i båda ändor för att komprimera och dekomprimera. Vinsterna om det blir några är små med tanke på de resurser som krävs och knappast värt besväret i en minnessnål tillämpning.
Protokollet utför samma tjänst som SLIP och CSLIP,
men kan göra mycket mer än så. Det går att bygga
ut PPP för att konfigurera andra protokoll, komprimera protokollhuvudena
och mycket mer. All utbyggbarhet och flexibilitet gör att PPP kräver
mer resurser.
I många sammanhang där det inte är så begränsat med resurser skulle PPP vara det rätta protokollet, men inte här. Om det behövs dynamisk konfigurering av något protokoll så kan det lätt lösas genom att lägga till något applikationsprotokoll som till exempel DHCP.
För att öka prestandan tänkte jag att drivrutinen skulle ta över länklagrets arbete. Det innebär att SLIP byggs in i drivrutinen. Genom att utföra SLIP substitutionen direkt när data skrivs till nätverket behövs ingen extra buffert allokeras och inga kopieringar behövs. Drivrutinen med SLIP får då kommunicera direkt mot anslutningsgränssnittet med signaler.
Gränssnittet är till för att koppla ihop anslutningar
med nätverkslagret. I gränssnittet finns bara funktioner för
att tilldela IP konfigurationer och att koppla kanaler till anslutningar.
Att konfigurera en anslutning kan inte göras här utan det måste
göras innan anslutningen registreras.
Varje anslutning måste registreras och får då ett anslutnings ID som används för att referera till anslutningen. Sedan kan en eller flera IP konfigurationer tilldelas anslutningen och en eller flera kanaler kopplas till anslutningen. Kanalen behövs för att applikationen ska kunna nå anslutningen och IP konfigurationen behövs för att ge anslutningen en adress i nätverket. Utan adress i nätverket kan en anslutning endast ta emot paket som är riktade till alla i hela nätverket. Mer om IP konfigurationer och kanaler finns under respektive rubrik IP och applikationsgränssnitt.
För att tillhöra Internet eller ett Intranet så
måste nätverksprotokollet vara IP.
Innan IP har tilldelats en konfiguration kan bara paket riktade till hela nätverket tas emot eller sändas. En IP konfiguration innehåller IP adress och subnätmask. Det är allt som behövs för att kunna avgöra adressen på ett paket.
Protokollet levererar paket otillförlitligt och förbindelselöst mellan två noder i ett nätverk. Standarden för IPv4 antogs i september 1981 och det märks tyvärr att den är relativt gammal. Därför har jag beslutat att stryka alla tillval (eng. Options). De tillval som finns är begränsade och används inte annat än lokalt och även då är det sällsynt. Några av de tjänster som tillvalen skulle tillgodose utförs idag av ICMP, som även används för felmeddelande.IPv4 har ett fält kallat TOS som inte används och jag tänkt sätta det till noll (normalfallet). Om TOS skulle börja användas av routers så kommer paketen inte att prioriteras, men det är enkelt att i efterhand lägga till TOS.
Inga tillval i IP kommer att implementeras. De tillval som finns är alltför begränsade eller används inte. Enligt RfIH behöver bara två tillval hanteras och det är Source Routing (både Loose och Strict). Den här protokollsviten begränsas till att bara utgöra ändpunkt i en förbindelse och behöver inte hantera tillvalet eftersom antingen är noden ändpunkt och ska ha paketet eller så har paketet hamnat fel och ska kastas.
Transportlagret ser till att paket som nått sin destination
även når avsedd applikation. Protokollet ICMP måste inkluderas
eftersom IP använder det för felmeddelanden.
Det finns tre protokoll som vanligen används i transportlagret för en TCP/IP protokollsvit: ICMP, UDP och TCP. Det första (ICMP) måste inkluderas för att nätverkslagret ska fungera korrekt eftersom det används av IP för att skicka felmeddelanden. De andra två protokollen är däremot valbara. TCP är det mest använda protokollet och det krångligaste med egen flödeskontroll. En TCP implementation kan lätt vara för stor för vissa tillämpningar och bör därför gå att välja bort vid en kompilering. UDP är litet, enkelt och används oftast till transport av multimedia där paket som är försenade inte behövs längre. Realtidsegenskaperna är viktigare än paketen. Dessutom kan UDP användas för multicasting och det kan inte TCP.
Protokollet är en del av IP, men också ett transportprotokoll
för meddelanden. Det finns åtta olika ICMP meddelanden, som
kan delas in i två grupper: felmeddelanden och informationsmeddelanden.
Det enda informationsmeddelande som måste implementeras enligt RfIH och som kommer att implementeras är echo. De andra informationsmeddelandena finns det ingen anledning att implementera. Timestamp meddelandet går inte att implementera eftersom systemet inte kan räkna fram tiden enligt universell tid.
Protokollet är ett väldigt enkelt transportprotokoll
för otillförlitlig överföring mellan applikationer
över nätverket. UDP används mest av multimedia tillämpningar.
UDP ger inga garantier för att paket når mottagaren. Om något fel uppstår är det upp till applikationen att ta till åtgärder när så behövs. UDP fungerar även för de flesta applikationsprotokoll som klarar TCP.
Ett TCP protokollhuvud är på 20 bytes om inga tillval (eng. Options) används. Det finns bara ett tillval och det är MSS, som anger största paket som kan tas emot. När en förbindelse upprättas skickas även MSS med om något annat värde än minsta tillåtna MSS på 536 bytes ska användas. För en minnessnål svit är små paket en fördel och därför behöver inga tillval tas med. MSS är ett sätt att undvika fragmentering och genom att sätt MSS till MTU minus protokollhuvuden eller lägre så kommer ett TCP paketen inte att fragmenteras. Nätverksprotokollet IP kräver att alla som implementerar det måste kunna ta emot paket på minst 576 bytes, varav 536 bytes data och 40 bytes protokollhuvuden.
Alla paket som skickas med TCP får ett paket ID, och det data som utgör ett eller flera paket är låst tills en bekräftelse på att mottagaren har fått alla paket inkommit. För innan någon sådan bekräftelse inkommit kan det hända att tidsgränsen för omsändning överskrids och att nytt paket måste skickas.
Applikationsgränssnittet brukar på engelska benämnas
"socket layer" och definiera ett objekt kallat "socket". En socket är
det data som unikt identifierar en applikation någonstans i nätverket.
När en applikation signalerar att den vill ha en socket, så erhåller den ett socket ID, som används för att referera till socketen när den används. Efter att den har skapats kan den konfigureras och kopplas till en anslutning. Varje anslutning kan ha en eller flera IP konfigurationer och en socket kan välja vilken den vill använda. När ett paket levereras till applikationen kommer även socket ID att bifogas. En socket innehåller bland annat anslutnings ID, IP-konfigurations ID, port nummer, protokoll ID, destination, med mera.
Ofta används en hashtabell för att lagra alla portnummer, men det kommer troligen inte att finnas tillräcklig många samtidiga kanaler för att berättiga en hashtabell. Annars så kommer varje anslutning att ha en lista över de kanaler som är kopplade till sig och kan gå igenom den listan för att hitta rätt port för ett UDP eller TCP paket. Det skulle kunna vara ett kompileringsbeslut om lista eller hashtabell ska användas.
Applikationer kommer att anropa protokollsviten med signaler och då är hur applikationen är programmerad som avgör om det är en synkron eller asynkron användarmodell som används. För att det ska vara en synkron modell krävs att applikationen stannar i väntan på bekräftelsesignal från sviten innan den kan fortsätta köra. Applikationen måste dessutom tänka på att inte ändra i en buffert som är skickad ut på nätverket med TCP tills en bekräftelse har kommit på att bufferten är mottagen. Om ett paket som är skickat med UDP går förlorat så kan ett ICMP meddelande skickas om att så är fallet och då är det upp till applikationen att avgör om paketet ska skickas igen och i så fall ha kvar bufferten. Men eftersom UDP inte ger några paket ID kan det vara svårt att säga vilket paket som gått förlorat om flera har sänts.
I applikationslagret inkluderas alla protokoll och applikationer
som använder applikationsgränssnittet för att kommunicera
över nätverket. Alla protokoll i det här lagret ligger utanför
ramarna för mitt exjobb.
Det finns många intressanta protokoll som kan implementeras i det här lagret, till exempel FTP (eng. File Transfer Protocol), HTTP (eng. Hyper-Text Transfer Protocol), NTP (Network Time Protocol), DHCP (eng. Dynamic Host Configuration Protocol), DNS klient (eng. Domain Name Service), med flera.
DHCP ger ett ramverk för att skicka konfigurationsparametrar till en klient över ett TCP/IP nätverk.Protokollet BOOTP (eng. Boot Protocol) utgör grunden för DHCP och DHCP bättrar bara på BOOTP med några ytterligare tillval (eng. Options) och några tillägg. Bland tilläggen finns konfigurering av klienter som inte använder ethernet och automatisk allokering av användbara adresser. DHCP som inte är en fastslagen standard än har ändå blivit vanligt för att konfigurera datorer dynamiskt i TCP/IP nätverk och kan användas även för den här protokollsviten för samma ändamål. Det är framförallt nätverkslagret som konfigureras av DHCP även om andra protokoll än IP också kan konfigureras.
Det är bra för applikationerna om de vet hur stort minnesbehov protokollsviten har eller åtminstone hur mycket den har som mest. Det måste finnas någon begränsning på hur mycket minne sviten kan ha allokerat samtidigt. Bland annat behövs det för TCP för att flödeskontrollen ska fungera effektivt. En övre gräns för storleken på paketen kommer alltså att finnas. Paket som är större än kvarvarande minnesutrymme kastas och ett felmeddelande skickas.
För inkommande IP paket kan de första 8 byten läsas och sedan kan IP avgöra hur stort paket det är frågan om och rätt storlek på buffert kan allokeras även om paketet är ett fragment i en serie av paket. Det krävs fortfarande att det finns utrymme för hela bufferten, annars måste paketet kastas och felmeddelande skickas.
Enligt alla standarderna ska en massa statistik insamlas under drift. Det tar en del minne och det finns ingen direkt nytta med det förutom i debugging syfte. Sedan finns det ju problem med hur statistiken ska göras tillgänglig. Att implementera SNMP (eng. Simple Network Management Protocol) eller liknande ligger utanför mitt exjobb. Det finns inget filsystem att spara på och det finns ingen skärm att skriva ut till. Därför tycker jag att det är onödigt att spara på statistiken. Den tar ju trots allt en del minne i den i övrigt minnessnåla protokollsviten.
Shrikumar har gjort en implementation på en 12-bitars processor och skriver att den är komplett enligt RfIH och får plats på bara 436 instruktioner handskriven assembler kod.