From 04e68443040c7abad84d66477e98f93bed701760 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Mon, 4 Feb 2019 13:09:03 +0100 Subject: Initial import --- system/net/1.7.5/doc/EUMEL Netz | 832 +++++++++++ system/net/1.7.5/src/basic net | 840 +++++++++++ system/net/1.7.5/src/callee | 14 + system/net/1.7.5/src/net inserter | 50 + system/net/1.7.5/src/net manager-M | 302 ++++ system/net/1.7.5/src/net report-M | 29 + system/net/1.8.7/doc/netzhandbuch | 2045 +++++++++++++++++++++++++++ system/net/1.8.7/doc/netzhandbuch.anhang | 58 + system/net/1.8.7/doc/netzhandbuch.index | 259 ++++ system/net/1.8.7/source-disk | 1 + system/net/1.8.7/src/basic net | 1148 +++++++++++++++ system/net/1.8.7/src/net files-M | 5 + system/net/1.8.7/src/net hardware interface | 389 +++++ system/net/1.8.7/src/net inserter | 145 ++ system/net/1.8.7/src/net manager | 797 +++++++++++ system/net/1.8.7/src/net report | 41 + system/net/1.8.7/src/netz | 20 + system/net/1.8.7/src/port server | 164 +++ system/net/1.8.7/src/printer server | 99 ++ system/net/1.8.7/src/spool cmd | 112 ++ system/net/1.8.7/src/spool manager | 915 ++++++++++++ system/net/unknown/doc/EUMEL Netz | 829 +++++++++++ 22 files changed, 9094 insertions(+) create mode 100644 system/net/1.7.5/doc/EUMEL Netz create mode 100644 system/net/1.7.5/src/basic net create mode 100644 system/net/1.7.5/src/callee create mode 100644 system/net/1.7.5/src/net inserter create mode 100644 system/net/1.7.5/src/net manager-M create mode 100644 system/net/1.7.5/src/net report-M create mode 100644 system/net/1.8.7/doc/netzhandbuch create mode 100644 system/net/1.8.7/doc/netzhandbuch.anhang create mode 100644 system/net/1.8.7/doc/netzhandbuch.index create mode 100644 system/net/1.8.7/source-disk create mode 100644 system/net/1.8.7/src/basic net create mode 100644 system/net/1.8.7/src/net files-M create mode 100644 system/net/1.8.7/src/net hardware interface create mode 100644 system/net/1.8.7/src/net inserter create mode 100644 system/net/1.8.7/src/net manager create mode 100644 system/net/1.8.7/src/net report create mode 100644 system/net/1.8.7/src/netz create mode 100644 system/net/1.8.7/src/port server create mode 100644 system/net/1.8.7/src/printer server create mode 100644 system/net/1.8.7/src/spool cmd create mode 100644 system/net/1.8.7/src/spool manager create mode 100644 system/net/unknown/doc/EUMEL Netz (limited to 'system/net') diff --git a/system/net/1.7.5/doc/EUMEL Netz b/system/net/1.7.5/doc/EUMEL Netz new file mode 100644 index 0000000..ad39db3 --- /dev/null +++ b/system/net/1.7.5/doc/EUMEL Netz @@ -0,0 +1,832 @@ +#type ("trium8")##limit (11.0)# +#start(2.5,1.5)##pagelength (17.4)# +#block# +#headeven# + +% EUMEL-Netzbeschreibung + + +#end# +#headodd# + +#center#Inhalt#right#% + + +#end# + +#type ("triumb12")# +1. Einleitung + + +Teil 1: Netz einrichten und benutzen +#type ("trium8")# + +1. Benutzung des Netzes + +2. Hardwarevoraussetzungen + +3. Einrichten des Netzes + +4. Informationsmglichkeiten + +5. Eingriffsmglichkeiten + +6. Fehlerbehebung im Netz + +#type ("triumb12")# + +Teil 2: Arbeitsweise der Netzsoftware +#type ("trium8")# + +1. Die Netztask + +2. Protokollebenen + +3. Stand der Netzsoftware + +#page# +#headodd# + +#center#Einleitung#right#% + + +#end# + +#type("triumb12")# +1. Einleitung #type("trium8")# + + +Das EUMEL-Netz dient dazu mehrere EUMEL-Rechner (sog. Stationen) mit- +einander zu koppeln. Diese Kopplung wird von Betriebsystem dazu benutzt, das +Sendungskonzept (siehe Systemhandbuch 1.7, Intertaskkommunikation) so auszu- +dehnen, da Tasks verschiedener Stationen einander Datenrume zusenden +knnen. Auf dem Sendungskonzept aufbauende Konzepte nutzen daher automa- +tisch das Netz aus: So ist es z.B. mglich + +- von einer Station aus auf einer anderen zu Drucken, + +- in PUBLIC einer anderen Station Dateien zu sichern (save), vorausgesetzt, da + PUBLIC dort ein free global manager ist, + +- auf einer anderen Station zu archivieren (z.B. wenn das eigene Archivlaufwerk + defekt ist oder ein anderes Format hat). + +Das Netz kann ab EUMEL-Version 1.7.3 eingesetzt werden. + + +#type("triumb12")# +Teil 1: Netz einrichten und benutzen + +1. Benutzung des Netzes #type("trium8")# +#headodd# + +#center#Teil 1: Netz einrichten und benutzen#right#% + + +#end# + + Zur Benutzung des Netzes stehen folgende Operatoren und Prozeduren zur + Verfgung: + + +1.1 + + TASK OP / (INT CONST station, TEXT CONST taskname) + + liefert die Task #on("bold")#taskname#off("bold")# von der Station #on("bold")#station#off("bold")#. + + Wenn die Station #on("bold")#station#off("bold")# nicht am Netz ist oder nicht eingeschaltet ist, wird + solange gewartet, bis das der Fall ist. + + Fehlerflle: + + - task "..." gibt es nicht + + Die angeforderte Task gibt es in der Zielstation nicht. + + - Collectortask fehlt + + Das Kommando #on("bold")#define collector#off("bold")# wurde nicht gegeben (siehe 4.2). + + - Station x antwortet nicht + + Eine nicht vorhandene oder abgeschaltete Station wurde angesprochen. + Hinweis: Dieser Fehler wird angenommen, wenn eine berwachungszeit + von ca. 30 Sekunden verschrichen ist, ohne da Station x die + Taskidentifikation angeliefert hat. + + Beispiel: + + list (5/"PUBLIC") + + Dateiliste von PUBLIC auf Station 5 wird angefordert. + +1.2 + + TASK OP / (INT CONST station, TASK CONST task) + + liefert + + station / name (task) . + + + Beispiel: + + list (4/archive) + + +1.3 + + INT PROC station (TASK CONST task) + + liefert die Stationsnummer der Task #on("bold")#task#off("bold")#. + + Beispiel: + + put (station (myself)) + + gibt die eigene Stationsnummer aus. + + +1.4 + + PROC archive (TEXT CONST archivename, INT CONST station) + + dient dazu das Archiv auf der Station #on("bold")#station#off("bold")# anzumelden. + + Beispiel: + + archive ("std", 4); list (4/archive) + + gibt das Inhaltsverzeichnis der Archivfloppy im Laufwerk der Station 4 aus. + Hinweis: Vergessen Sie bei solchen Querarchivierungen nicht die Stations- + angabe bei jedem einzelnen Archivkommando (z.B fetch ("xxx", #on("bold")#4/#off("bold")# + archive). + Hinweis: Querarchivieren ist langsam. Verwenden Sie es nur, wenn Sie Flop- + pyformate umsetzen wollen. + + +1.5 + + PROC free global manager + + dient dazu, die eigene Task ber das Netz ansprechbar zu machen. Jede + andere Task im Netz kann dann die blichen Manageraufrufe ('save', 'fetch', + u.s.w.) an die eigene Task machen, sofern diese nicht an ein Terminal gekop- + pelt ist. + + Die Task wird (wie bei 'break') abgekoppelt und meldet sich in Zukunft mit + 'maintenance' statt mit 'gib kommando'. + + Beispiel: + + An Station 4 ruft man in der Task 'hugo' das Kommando #on("bold")#free global manager#off("bold")# + auf. Anschlieend kann man von jeder Station aus z.B. 'list (4/"hugo")' u.s.w. + machen. + + +1.6 + + TEXT PROC name (TASK CONST t) + + Diese (schon immer vorhandene) Prozedur wurde dahingehend erweitert, da der + Name einer Task einer anderen Station ber Netz angefordert wird. + + Fehlerfall: + + Station x antwortet nicht + + + + +#type("triumb12")#2. Hardwarevoraussetzungen#type("trium8")# + +2.1 Zwei Stationen + + Sie knnen zwei Stationen miteinander Vernetzen, wenn Sie dafr an jeder + Station eine V24-Schnittstelle zur Verfgung stellen. + + Diese beiden Schnittstellen verbinden Sie mit einem Kabel zur Rechner- + kopplung (siehe Systemhandbuch 1.7 Teil 2). + +2.2 Mehrere Stationen + + Wenn Sie mehr als zwei Stationen vernetzen wollen, brauchen neben je + einer V24 an jeder Station noch je eine Netzanschlubox. + + Jede Box besitzt eine V24-Schnittstelle zum Anschlu an die V24- + Schnittstelle der zugeorneten Station und eine weitere Schnittstelle zur + Verbindung der Boxen untereinander. + + +#type("triumb12")#3. Einrichten des Netzes #type("trium8")# + +Hinweis: Dieses Kapitel ist nur fr Systembetreuer wichtig. + +3.1 Legen Sie Stationsnummern fr die am Netz beteiligten Rechner fest (von 1 an + aufsteigend). + + Die Boxen haben ebenfalls Stationsnummern. Die Stationsnummern der Box + und des zugeordneten Rechners mssen bereinstimmen. + + +3.2 Holen Sie an jeder Station die Task #on("bold")#configurator#off("bold")# an ein Terminal und geben Sie + das Kommando #on("bold")#define collector ("net port")#off("bold")#. Geben Sie auerdem das + Kommando #on("bold")#define station (x)#off("bold")#, wobei #on("bold")#x#off("bold")# die gewhlte Stationsnummer ist. + + Hinweis: Taskkommunikationen, die zu dem Zeitpunkt laufen, fhren zu feh- + lerhaften Verhalten. Dies liegt daran, da durch #on("bold")#define station#off("bold")# alle + Task-Id's gendert werden mssen, weil eine Task-Id u.a. die + Stationsnummer der eigenen Station enthlt (siehe 2.3). TASK- + Variable, die noch Task-Id's mit keiner oder falscher Stationsnum- + mer enthalten, knnen nicht mehr zum Ansprechen einer Task + verwendet werden. + + Beispiel: Der Spoolmanager (siehe Benutzerhandbuch 1.7 Teil 12) richtet + beim Kommando #on("bold")#start#off("bold")# einen Worker ein und merkt sich dessen + Task-Id in einer TASK-Variablen, um sicherzustellen, da nur der + Worker Dateien zum Drucken abholt. Wird jetzt das Kommando #on("bold")# + define station#off("bold")# gegeben, kann der Spoolmanager seinen Worker + nicht mehr identifizieren, weil der Worker eine neue Task-Id er- + halten hat. Man mu daher den Worker lschen und mit dem + Kommando #on("bold")#start#off("bold")# im Spoolmanager wieder neu einrichten. + + + Sinnvollerweise gibt man #on("bold")#define station#off("bold")# sofort nach den Laden eines + frischen Systems von Archiv. + + Konfigurieren Sie mit dem Kommando #on("bold")#configurate#off("bold")# den fr das Netz vorgese- + henen Kanal auf + + - transparent + - 9600 Baud (Standardeinstellung der Boxen) + - RTS/CTS-Protokoll + - groen Puffer + - 8 bit + - even parity + - 1 stopbit. + + Falls diese Einstellungen nicht alle angeboten werden, klren Sie mit Ihrem + Rechnerlieferanten, ob und wie diese Einstellungen erreicht werden knnen. + Hinweis: Notfalls kann auf das RTS/CTS-Protokoll verzichtet werden, wenn + der Eingabepuffer der Station gro genug ist. Die Anzahl simultan + laufender Netzkommunikationen ist dann auf + + puffergre DIV 150 + + begrenzt (bei Z80, 8086: 3; bei M20: 10). + Hinweis: Es knnen auch andere Baudraten (2400, 4800, 19200) an der Box + eingestellt werden. + +3.3 Achten Sie bei der Verbindung von der Station zur Netzbox (bzw. zur Gegen- + station bei einem Zweistationennetz ohne Boxen) darauf, da neben den + Empfangs- und Sendeleitungen auch die Leitungen RTS und CTS verdrahtet + werden, also ein 5 poliges Kabel verwendet wird (siehe Systemhandbuch 1.7 + Teil 2). Die Pin-Belegung der Boxen entspricht den dortigen Angaben. + + Beispiel: + + Verbindung eines CSK-Systems mit der Box: + + Stecker Stecker + Pin Pin + + 2 <---------> 3 + 3 <---------> 2 + 4 <---------> 5 + 5 <---------> 4 + 7 <---------> 7 + + +3.4 Richten Sie eine Task #on("bold")#net#off("bold")# unter #on("bold")#SYSUR#off("bold")# ein und insertieren Sie dort die Datei- +en + + net report/M + basic net + net manager/M. + + Beantworten Sie die Frage nach dem Kanal fr das Netz und nach der Flu- + kontrolle (RTS/CTS). + + +#type("triumb12")#4. Informationsmglichkeiten #type("trium8")# + + In der Task #on("bold")#net#off("bold")# wird eine Datei #on("bold")#report#off("bold")# gefhrt in der Fehlersituationen des + Netzes verzeichnet werden. Diese Datei kann in jeder anderen Task mit #on("bold")#list + (/"net")#off("bold")# angezeigt werden. + + In jeder Task kann durch das Kommando #on("bold")#list (/"net port")#off("bold")# eine bersicht ber + die momentan laufenden Netzbertragungen der eigenen Station erhalten + werden. + + +#type("triumb12")#5. Eingriffsmglichkeiten #type("trium8")# +#headodd# + +#center#Eingriffsmglichkeiten#right#% + + +#end# + +5.1 Jede Task kann Sende- und Empfangsstrme, die bei #on("bold")#list (/"net port")#off("bold")# gemel- + det worden sind und die eigene Task betreffen, abbrechen. Hierzu ist das + Kommando #on("bold")#erase ("x",/"net port")#off ("bold")# zu geben, wobei x die Stromnummer (aus + dem 'list') ist. + + Unberechtigte Lschversuche werden abgewiesen. + + Von der Task 'net' aus knnen jedoch damit beliebige Strme abgebrochen + werden. + +5.2 Durch das Kommando #on("bold")#start#off("bold")# kann von der Task 'net' aus das Netz neu gestartet + werden. Dabei werden alle augenblicklichen Netzkommunikationen gelscht. + Die Tasks 'net port' und 'net timer' werden dabei gelscht und neu eingerich- + tet. + + #on("bold")#start (kanal, quit)#off("bold")# wirkt wie #on("bold")#start#off("bold")#. Zustzlich wird als Netzkanal 'kanal' eingestellt + und maximal 'quit' Empfangsstrme zugelassen. 'quit' ist auf 3 zu setzen, + wenn der Kanal ohne RTS/CTS angeschlossen ist (siehe 3.2). + + +#type("triumb12")#6. Fehlersuche im Netz #type("trium8")# + + Fehler im Netz knnen sich verschiedenartig auswirken. Im Folgenden wird auf + einige Beispiele eingegangen: + + Beispiel: + + Auf #on("bold")#list (4/public)#off("bold")# erfolgt die Meldung 'Station 4 antwortet nicht'. + + Fehlermglichkeiten: + + - Station 4 gibt es nicht am Netz. + Abhilfe: Richtige Station angeben. + + - Station 4 ist nicht eingeschaltet. + Abhilfe: Station 4 einschalten. Kommando erneut geben. + + - Netztask an Station 4 ist nicht arbeitsfhig. + Abhilfe: Kommando 'start' in der Task 'net'. + + - Stationsnummern und Boxnummern stimmen nicht berein. + Abhilfe: Mit 'define station' Stationsnummern korrigieren (siehe 3.2). + + - Verbindung Rechner/Box am eigenen Rechner oder an Station 4 fehlt. + Abhilfe: Verbindungen berprfen. Durch Ansprechen einer dritten Station + kann oft schnell geklrt werden, welche Rechner/Box-Verbindung + defekt sein mu. + + - Verbindung der Boxen untereinander defekt. + Abhilfe: Fehlende Verbindung, Masseschlu und Dreher (keine 1:1 Ver- + bindung) berprfen und beheben. + Hinweis: Liegt z.B. ein Masseschlu vor, so kann es durchaus sein, da + Boxen, die nicht in der Nhe des Masseschlu stehen noch mitei- + nander arbeiten knnen. Man kann aus der Tatsache, da zwei + Boxen miteinander arbeiten knnen, also nicht schlieen, da man + nicht nach diesem Fehler suchen mu. + + + Beispiel: + + Auf #on("bold")#list (4/public)#off("bold")# erfolgt keine Reaktion. + + + - Station 4 ist whrend dieser Sendung zusammengebrochen. + Abhilfe: Station 4 wieder starten. Die Bearbeitung des 'list'-Kommandos + wird automatisch wieder aufgenommen. + + - PUBLIC auf Station 4 ist nicht im Managerzustand. + Abhilfe: PUBLIC in den Managerzustand versetzen. + + + Hinweis: Das Netz hat nocht nicht die volle Sendungslogik des EUMEL. So + wird nur ca. 10 Minuten lang versucht, eine Sendung zuzustellen. + Danach wird die Sendung gelscht. Ist dies eingetreten, so mu + das list-Kommando erneut gegeben werden. + + - Fehler in der Netzhardware. + berprfen Sie, ob + + - die Boxen eingeschaltet sind, + - die Bereitlampe blinkt (wenn nicht: RESET an der Box) + - die V24-Kabel richtig stecken, + - die Boxen untereinander verbunden sind (1 zu 1 Verbindungen der 5 + poligen Diodenbuchsen). + + + - Die Netzsoftware ist auf einen nicht vorhergesehenen Fehler gelaufen. + Dieser wird im Report vermerkt. + Abhilfe: Geben Sie in der Task #on("bold")#net#off("bold")# das Kommando #on("bold")#start#off("bold")#. Dadurch wird die + Netzsoftware neu gestartet. Alle Netzkommunikationen dieser + Station gehen verloren. + + + Beispiel: + + Auf #on("bold")#list (4/public)#off("bold")# erfolgt die Meldung 'Collectortask fehlt'. + + - In der Task 'configurator' wurde das Kommando 'define collector' (siehe 3.2) + nicht gegeben. + + - Die Task 'net port' existiert nicht mehr. + Abhilfe: Kommando 'start' in der Task 'net'. + + + Beispiel: + + Nach #on("bold")#fetch ("hugo",4/public)#off("bold")# sind Teile von der Datei "hugo" verflscht. + + - Die V24-Verbindung zur Box ist nicht in Ordnung. + Abhilfe: Abstand zwischen Rechner und Box verkrzen; Baudrate ernie- + drigen; Durch Wechseln der V24-Schnittstelle feststellen, ob + diese defekt ist. + Hinweis: Die Verbindung zwischen den Boxen ist durch Prfsummen abge- + sichert (Hardware). + +#headodd# + +#center#Teil 2: Arbeitsweise der Netzsoftware#right#% + + +#end# +#page# +#type("triumb12")# + +Teil 2: Arbeitsweise der Netzsoftware + + +1. Die Netztask #type ("trium8")# + +In diesem Kapitel wird beschrieben, wie eine Netztask in das System +eingebettet ist und welche Aufgaben sie hat. Unter Einhaltung dieser +Konzepte kann die ausgelieferte Netztask so gendert werden, da sie +beliebige andere Netzhardware untersttzt. Z.Zt. ist die Netzsoftware noch +nicht so gegliedert, da nur eine hardwareabhngige Komponente ausgetauscht +werden mu. + +Die Kommunikation zwischen Tasks im EUMEL-Betriebssystem basiert auf einem +Rendevouskonzept: Die Zieltask einer Sendung mu empfangsbereit sein, wenn die +Quelltask sendet. + +Die Kommunikationsprozeduren auf der niedrigsten Ebene sind 'send' (Senden) +und 'wait' (Warten auf Empfang). Bei der Kommunikation werden eine Integer +'code' und ein Datenraum 'dr' bergeben. 'code' mu >= 0 sein, da negative +Codes systemintern verwandt werden. Ist die empfangende Task an einen Kanal +gekoppelt ('continue'), so fhrt eine Zeicheneingabe auf diesem Kanal dazu, +da eine +Sendung mit dem Code -4 ankommt. Die Eingabedaten mssen mit den blichen +Eingabeprozeduren ('inchar' u.s.w.) abgeholt werden. Der bermittelte Datenraum +und die Absendertask sind dabei ohne Bedeutung und drfen nicht interpretiert +werden. + +Die Prozedur 'send' hat einen Rckmeldeparameter, der besagt, ob die Sendung +bermittelt wurde. Gibt es die Zieltask nicht oder steht sie nicht im 'wait', so kann +die Sendung nicht bermittelt werden. + + +Ein Entwicklungskriterium fr das EUMEL-Netz war es, mglichst wenig Unter- +sttzung von der virtuellen EUMEL-Maschine (EUMEL0) zu fordern, damit weit- +gehend in ELAN programmiert werden kann. Dadurch ist es mglich eine (privili- +gierte) Task mit der Netzabwicklung zu betrauen. + +Zunchst wird auf die EUMEL0-Untersttzung eingegangen: + +1.1. Es gibt die Prozedur 'define collector', mit der die fr das Netz verantwort- + liche Task der EUMEL0-Maschine bekannt gemacht wird. Diese Task wird im + folgenden Collector genannt. + +1.2. Es gibt die Prozedur 'define station', die fr den Rechner eine Stationsnum- + mer einstellt. Anhand dieser Nummer werden die Rechner eines Netzes un- + terschieden. Das Einstellen bewirkt, da fr alle Tasks die Stationsnummer in + ihre Task-Id eingetragen wird (Task-Id's sind die Werte, die der Typ TASK + annehmen kann). + +1.3. Der Befehl 'station (task)' liefert die Stationsnummer der 'task'. So liefert z.B. + 'station (myself)' die Stationsnummer des eigenen Rechners. + +1.4. Eine Sendung, deren Zieltask in einem anderen Rechner liegt (also station + (ziel) <> station (myself)), wird auf die Collectortask geleitet. + +1.5. Es gibt eine Prozedur 'collected destination', die es dem Collector erlaubt, die + eigentliche Zieltask einer auf ihn geleiteten Sendung zu erfahren. + +1.6. Es gibt eine Variante der Prozedur 'send', die es dem Collector gestattet, der + Zieltask eine beliebige andere Task als Absender vorzumachen. + +1.7. Es gibt eine spezielle Task-Id 'collector', durch die der augenblicklich ein- + gestellte Collector erreicht wird. Diese wird als Zieltask beim Aufruf der Ver- + mittlungsdienste angegeben (siehe 2.5). Eine Sendung an 'collector' wird von + EUMEL0 an den derzeitigen Collector geschickt. + +Ein Collector kann also auf drei Wegen von den brigen Tasks desselben Rechners +Sendungen erhalten: + + 1. ber ein normales Send (z.B. bei 'list (/"net port")', wenn "net port" der der- + zeitige Collector ist), + + 2. ber ein Send an die Task 'collector' (s.u.) und + + 3. als umgeleitete Sendung (z.B. bei 'list' an eine Task auf einem anderen + Rechner). + +Der Collector kann diese Flle anhand von 'collected destination' unterscheiden. + +Die Punkte 1.4...1.6 dienen dazu, den Collector fr ber Netz kommunizierende +Task unsichtbar zu machen: Der Collector taucht nicht als Ziel oder Quelle von +Sendungen auf. Das ist notwendig, damit normale Tasks sich nicht darum kmmern +mssen, ob eine Sendung bers Netz geht oder im eigenen Rechner bleibt. + +Wenn ein Datenraum an einen anderen Rechner geschickt wird, mu der gesamte +Inhalt (z. Zt. max. 1 MB) bertragen werden. Dies macht bei der blichen Netz- +hardware eine Zerlegung in Packete ntig (siehe Systemhandbuch 173, Teil 4, +Punkt 5). Fr Netze ber V24-Kanle stehen spezielle Blockbefehle zur verf- +gung: + +1.8. blockin / blockout (dr,seite,512+abstand,anzahl,rest) + + Es werden maximal 'anzahl' Bytes transferiert. In 'rest' wird zurckgemeldet, + wieviel Bytes nicht bearbeitet wurden (z.B. weil der Kanal nichts anliefert). + Bearbeitet werden die Bytes + + 'seite' * 512 + 'abstand' + + bis maximal + + 'seite' * 512 + 'abstand' + 'anzahl' - 1 + + Der Kanal, an den die Task gekoppelt ist, wird dabei ber Stream-IO (d.h. + 'incharety' bei 'blockin' bzw. 'out' bei 'blockout') angesprochen. + + Hinweis: Die Anforderung darf nicht ber Seitengrenze gehen, d.h. + + 'abstand' + 'anzahl' <= 512 + + mu erfllt sein. + + +Eine Netzsendung luft wie folgt ab: + +Die Task q auf Rechner rq mache ein 'send' an die Task z auf Rechner rz. + +1. Die Prozedur send ist ein EUMEL0-Befehl. Die EUMEL0-Ebene erkennt, da + die Sendung an die Station rz geht, da die Stationsnummer in der Task-Id + enthalten ist. Daher wird die Sendung zum Collector, den EUMEL0 wegen 'de- + fine collector' kennt, umgeleitet. + +2. Die Task Collector empfngt ber 'wait' den Datenraum, den Sendecode und + die Absendertask q. Die Zieltask z erfhrt sie durch 'collected destination'. + +3. Der Collector nimmt Kontakt mit dem Collector des Rechner rz, dessen Sta- + tionsnummer ja 'station(z)' ist, auf und bermittelt diesem Sendecode, Quelltask + (q), eigentliche Zieltask (z) und den Datenraum. Da die Collectoren in ELAN + geschrieben sind, knnen sie an beliebige Netzhardware und Protokolle ange- + pat werden. + +4. Der Collector auf Rechner rz verwendet das spezielle 'send', um der Zieltask die + Sendung zuzustellen. Dadurch erscheint nicht der Collector sondern die Task q + als Absender der Sendung. + +Zur Abwicklung der Vermittlungsebene (Teil 1: 2.4) mu der Collector noch +spezielle Funktionen beherrschen. Diese sind + + der /-Operator (Taskname in Task-Id wandeln) und + die name-Prozedur (Task-Id in Namen wandeln). + +Der /-Operator macht eine Sendung an den 'collector', wobei im Datenraum der +Name der Task steht und der Sendecode gleich der Stationsnummer ist (siehe +Quellcode 173, Packet tasks). Der Collector setzt sich mit dem Collector dieser Sta- +tion in Verbindung, damit dieser die Task-Id ermittelt und zurckschickt. Der +eigene Collector schickt dann dem /-Operator als Antwort einen Datenraum, der +die Task-Id enthlt. + +Umgekehrt luft 'name' ab: Wenn die Task-Id von einer fremden Station ist, +schickt 'name' eine Sendung an den 'collector', wobei im Datenraum die Task-Id +steht und Sendecode = 256 ist. Der Collector entnimmt die Stationnummer der +Task aus der Task-Id und lt sich vom entsprechenden Collector den Tasknamen +geben. Dieser wird der 'name'-Prozedur im Antwortdatenraum bergeben. + +#type ("triumb12")#2. Ebenen #type("trium8")# + +In diesem Kapitel werden die Protokollebenen fr das Netz beschrieben, wie +sie die ausgelieferte Netzsoftware benutzt und erwartet. Bei anderer +Netzhardware mssen die Ebenen 1 bis 3 ausgetauscht werden. Unter Einhaltung +der im vorigen Kapitel beschriebenen Randbedingungen knnen auch die hheren +Ebenen gendert werden. + + +2.1 Physikalische Ebene + + 2.1.1 Station <--> Box + + V24-Schnittstelle mit RTS/CTS-Handshake. Vollduplex. + + 2.1.2 Box <--> Box + + RS422 ber 2 verdrillte Leitungspaare (Takt und Daten). + +2.2 Verbindungsebene + + 2.2.1 Station <--> Box + + Asynchron + 8 Bit + Even Parity + 2400/4800/9600/19200 Baud (einstellbar ber Ltbrcken) + + 2.2.2 Box <--> Box + + SDLC + 400 KBaud + +2.3 Netzebene + + 2.3.1 Station <--> Box + + Telegrammformat: STX, , , , <(n-4) byte> + + ist Lngenangabe ( 8 <= n <= 160) + , sind Stationsnummern. Diese mssen an den je- + weiligen Boxen ber Ltbrcken eingestellt sein. + + Box --> Station: + + Ein Telegramm kommt nur bei der Station an, bei deren Box die + Nummer eingestellt ist. Dadurch ist ein Mithren fremder + bertragungen nicht mglich (Datenschutz). + + Zwischen Telegrammen knnen Fehlermeldungen der Box (Klartext) + bermittelt werden (z.B. 'skipped x', wenn ein STX von der Box er- + wartet wurde, aber 'x' von der Station ankommt). + + Station --> Box: + + Ein Telegramm wird nur abgeschickt, wenn mit der einge- + stellten Nummer bereinstimmt (Datenschutz: Man kann nicht eine + beliebige Station zu sein vorschwindeln, es sei denn man hat physi- + schen Zugriff zur Box und stellt dort die Stationsnummer um). + + 2.3.2 Box <--> Box + + Telegrammformat: FRAME, , , , + + + Eine Lngenangabe ist nicht ntig, da SDLC eine Rekonstruktion der + Lnge erlaubt. + + Telegramme mit falschen CRC-Code werden vernichtet. Auf hheren + Ebenen mu dies durch Zeitberwachung erkannt und behandelt + werden. + + +2.4 Transportebene + + Diese Ebene wickelt das Rendevous zwischen einer Task, die 'send' macht, + und einer Task, die im 'wait' steht, ab (siehe: EUMEL-Systemhandbuch). + + Der im 'send' angegebene Datenraum wird als Folge von Seiten (im + EUMEL-Sinne: Pagingeinheit und Allokiereinheit) bermittelt, wobei jede Seite + noch in 64 Byte groe Stcke zerlegt wird. Es werden nur echt allokierte Seiten + bermittelt. Um nicht jedes Telegramm voll qualifizieren zu mssen, wird + zunchst eine Art virtuelle Verbindung durch ein OPEN-Telegramm erffnet. + Danach folgen variable viele DATA-Telegramme. Beide Sorten werden durch + QUIT-Telegramme quittiert, um folgende Funktionen zu ermglichen: + + Flukontrolle (z.B. Zielrechner langsam) + Wiederaufsetzen (verlorene Telegramme) + Abbruch (z.B. weil Zieltask inzwischen beendet). + + Ein CLOSE-Telegramm ist nicht ntig, da das letzte DATA-Telegramm als + solches erkannt werden kann (siehe unten). + + 2.4.1 OPEN-Telegramm + + STX, 20, , , , , , + , , + + , siehe 2.3.1 + + Die Stromnummer identifiziert die virtuelle Verbindung. + Sie mu in den QUIT-Telegrammen angegeben wer- + den. + + -1 (Kennzeichen fr OPEN) + + Nummer der ersten echt allokierten Seite des Datenra- + ums (=-1, falls Nilspace) + + Taskid der sendenden Task + + Taskid der empfangenden Task + + Wert des im 'send' angegebenen Codes. + + 2.4.2 DATA-Telegramm + + STX, 74, , , , , <64 byte> + + wird von Telegramm zu Telegramm hochgezhlt. Dient + der berwachung gegen verlorengegangene Telegramme + bzw. durch Zeitberwachung verdoppelter Telegramme. + + Nummer der x.ten echt allokierten Seite des Datenra- + ums. (x = (+16) DIV 8). + + <64 byte> Nutzinformation. Diese gehrt zur Adresse a des Daten- + raums. + + a = N ( DIV 8 + 1) * 512 + + ( MOD 8) * 64 + + wobei N (x) die Nummer der x.ten Seite ist. + + Aus den Formeln ergibt sich, da diese Nummer schon in + einem vorhergehenden DATA/OPEN-Telegramm ber- + mittelt wurde (im Feld ). + + 2.4.3 QUIT-Telegramm + + STX, 8, , , , + + mu die Stromnummer sein, die in dem OPEN/DATA- + Telegramm stand, das quittiert wird. + + 0 : ok. Nchstes Telegramm schicken. + + -1: bertragung neu starten (mit OPEN), weil die + Empfangsstation das OPEN nicht erhalten hat. + + -2: bertragung ca. 20 Telegramme zurcksetzen. + + -3: bertragung abbrechen. + + +2.5 Vermittlungsebene + + Diese Ebene ist dafr zustndig, Tasknamen von Task auf anderen Stationen + in Taskids (Werte des Typs TASK) zu wandeln und umgekehrt. Hierzu wird im + entsprechenden OPEN-Telegramm der Code -6 (bzw. -7) als + eingetragen. Die Netzempfangstask erkennt diese Codes und wickelt die + Aufgaben selbst ab, soda es dabei nicht ntig ist, irgendeine Taskid der + Zielstation zu kennen. + + Dieses Verfahren ist mglich, weil im 'send' nur positive Codes erlaubt sind. + +2.6 Hhere Ebenen + + Hhere Ebenen sind nicht mehr netzspezifisch. Sie basieren alle auf dem + Send/Wait-Konzept des EUMEL. So gibt es z.B. den 'global manager', der + Aufbewahrung und Zugriff von Dateien in einer Task regelt. Dabei darf diese + Task (bei der Variante 'free global manager') auf einer beliebigen Station im + Netz liegen. Wegen des Rendevous-Konzepts knnen beliebige Sicherheit- + strategien benutzt werden (z.B.: Keine Dateien an Station 11 ausliefern). Von + groen Wert ist z.B., da man ohne weiteres das Archiv (Floppylaufwerk) einen + anderen Station anmelden und benuzten kann, wodurch eine einfache Kon- + vertierung von Floppyformaten mglich ist. Dies ist mglich, weil auch die Ar- + chiv-Task der Stationen sich an das Globalmanagerprotokoll halten. + + +#type("triumb12")# +Bemerkungen#type("trium8")# + +Fehlerbehandlung besteht bis Ebene 3 darin, fehlerhafte Telegramme einfach zu +entfernen. Die Ebene 4 berwacht den Netzverkehr sowieso ber Timeouts, die +eine Wiederhohlung eines Telegrammes bewirken, wenn die Quittung ausbleibt. + +Da bei der sendenden Station der ganze Datenraum zur Verfgung steht, ist eine +Fenstertechnik (wie bei HDLC) nicht ntig. Es kann zu jedem Zeitpunkt um beliebig +viele Telegramme zurckgesetzt werden. + +Da im EUMEL eine Textdatei ein Datenraum mit sehr komplexer Struktur ist (wegen +der Insert/Delete-Mglichkeiten, ohne den Rest der Datei zu schieben), ist es ein +hoher Aufwand, von einem fremden Betriebssytem her Textdateien ins EUMEL- +Netz zu senden. Fr solche Zwecke mu noch eine einfachere Dateistruktur defi- +niert werden und entsprechende Dateikonverter erstellt werden. + + + +#type("triumb12")#3. Stand der Netzsoftware #type("trium8")# + +Das EUMEL-System wickelt die Prozedur #on("bold")#send#off("bold")# ber das Netz ab, wenn die +Stationsnummer der Zieltask ungleich der eigenen Stationsnummer ist. Umge- +kehrt kann man der von der Prozedur #on("bold")#wait#off("bold")# gelieferten Absendertask die Absen- +derstation entnehmen (siehe Prozedur #on("bold")#station#off("bold")# in Abschnitt 3). + +Nicht untersttzt wird z.Zt. die Logik der Prozeduren #on("bold")#call#off("bold")# und #on("bold")#pingpong#off("bold")#. Diese +funktionieren nur in der gewohnten Weise, wenn die Zieltask in #on("bold")#wait#off("bold")# steht. Ist +die Zieltask lnger als ca. 10 Minuten #on("bold")#busy#off("bold")# oder nicht mehr vorhanden, geht die +Sendung einfach verloren (Gefordert ist: bei #on("bold")#call#off("bold")#: immer wieder versuchen; bei #on("bold")# +pingpong#off("bold")#: Rckmeldung -2). + +Wegen dieser Einschrnkung kann man z.B. ein sicheres Drucken von Station a +auf einen Drucker der Station b nur durch einen eigenen Spoolmanager auf +Station a verwirklichen. Die Einrichtung eines solchen Managers ist allerdings +sowieso sinnvoll, damit man + +- das normale 'print'-Kommando verwenden kann (statt z.B. save ("xxx", +4/printer);) und +- nicht zu warten braucht, bis die Datei bers Netz gesendet ist. + + + + + diff --git a/system/net/1.7.5/src/basic net b/system/net/1.7.5/src/basic net new file mode 100644 index 0000000..41c8402 --- /dev/null +++ b/system/net/1.7.5/src/basic net @@ -0,0 +1,840 @@ +PACKET basic net DEFINES (* D. Heinrichs *) + (* 02.10.85 *) + nam, + max verbindungsnummer, + neuer start, + packet eingang, + neue sendung, + zeitueberwachung, + verbindung, + loesche verbindung: + +TEXT PROC nam (TASK CONST t): + IF t = collector THEN name (t) + ELIF station (t) <> station (myself) + THEN "** fremd **" + ELSE name (t) + FI +END PROC nam; + +INT PROC tasknr (TASK CONST t): + IF t = collector THEN maxtasks + ELSE index (t) + FI +END PROC tasknr; + +LET + maxtasks = 127, + max strom = 20, + max strom 1 = 21, + stx = ""2"", + code stx = 2, + ack = 0, + nak = 1, + error nak = 2, + zeichen eingang = 4, + list code = 15, + fetch code = 11, + inspect code = 30, + continue code = 100, + erase code = 14, + report code = 99, + seiten groesse = 512, + dr verwaltungslaenge = 8, + dr verwaltungslaenge2=10, + nutzlaenge = 64, + openlaenge = 20, + vorspannlaenge = 10, + neue ack laenge = 10, + ack laenge = 8, + + (* Typen von Kommunikationsstrmen *) + + send wait = 0, + zustellung = 1, + call pingpong = 2, + call im wait = 3, + call im abbruch = 4, + call in zustellung = 5, + + (*quittungscodes*) + + ok = 0, + von vorne = 1, + wiederhole = 2, + loesche = 3, + beende = 4; + +LET STEUER = + STRUCT ( + INT head, + rechner nummern, + strom, + sequenz, + seitennummer, + TASK quelle,ziel, + INT sende code); + +BOUND STEUER VAR open block; + +BOUND STRUCT (STEUER steuer, INT typ) VAR info block; + +BOUND STRUCT ( + INT head, + rechner nummern, + strom, + sequenz, + seitennummer) VAR vorspann ; + +BOUND STRUCT ( + INT head, + rechner nummern, + strom, + code) VAR ack packet ; + +INT CONST max verbindungsnummer := max strom; + +BOOL PROC blockin (DATASPACE VAR ds, INT CONST seite, abstand, laenge): + INT VAR hilfslaenge:=laenge, code:= abstand+laenge+512; + REAL VAR time out := clock (1) + 10.0; + REP + blockin (ds,seite,code-hilfslaenge, hilfslaenge, hilfslaenge); + UNTIL hilfslaenge = 0 OR clock (1) > time out PER ; + hilfslaenge = 0 +END PROC blockin; + +PROC blockout (DATASPACE CONST ds, INT CONST seite, abstand, laenge): + INT VAR hilfslaenge:=laenge, code:= abstand+laenge+512; + REP + blockout (ds,seite,code-hilfslaenge, hilfslaenge, hilfslaenge); + UNTIL hilfslaenge = 0 PER +END PROC blockout; + + + + +DATASPACE VAR work space; + + +INT CONST packete pro seite:= seitengroesse DIV nutzlaenge, + packete pro seite minus 1 := packete pro seite -1, + datenpacketlaenge := vorspannlaenge + nutzlaenge; + +INT VAR err,strom; + +INT VAR own:=station (myself) , + quit max := 3, + quit zaehler := 3, + own256 := 256*own; +INT CONST stx open := code stx+256*openlaenge, + stx quit := code stx+256*acklaenge; + + ROW maxstrom1 STEUER VAR verbindungen; + ROW maxstrom1 DATASPACE VAR netz dr; + ROW maxstrom1 INT VAR zeit, typ; + FOR strom FROM 1 UPTO maxstrom1 REP vdr := nilspace; forget (vdr) PER; + ROW maxstrom INT VAR dr page ; + ROW maxtasks INT VAR alter call; + STEUER VAR opti; + +.vx : verbindungen (strom). + +vdr: netz dr (strom). + +falsche stromnummer: strom < 1 OR strom > maxstrom. + +call aufruf: typ(strom) >= call pingpong. + +alles raus: vx.seitennummer = -1 AND letztes packet der seite . + +letztes packet der seite : +(vx.sequenz AND packete pro seite minus 1) = packete pro seite minus 1. + +PROC neuer start (INT CONST empfangsstroeme): + workspace := nilspace; + open block := workspace; + info block := workspace; + vorspann := workspace; + ack packet := workspace; + FOR strom FROM 1 UPTO maxstrom1 REP + vx.strom := 0; forget (vdr) + PER; + INT VAR i; + FOR i FROM 1 UPTO maxtasks REP alter call (i) := 0 PER; + quitmax := empfangsstroeme; + own:=station (myself); + quit zaehler := quit max; + own256 := 256*own; + reset box. + +reset box: + out (90*""4""); + REP UNTIL incharety (1) = "" PER. + +END PROC neuer start; + +DATASPACE PROC verbindung (INT CONST nr): + infoblock.steuer := verbindungen (nr); + infoblock.typ := typ (nr); + workspace +END PROC verbindung; + +PROC neue sendung (TASK CONST q,z, INT CONST cod, DATASPACE CONST dr): + + naechste verbindung vorbereiten; + forget (vdr); vdr := dr; + IF z = collector + THEN + verbindungsebene + ELSE + sendung starten (q,z,cod) + FI. + +verbindungsebene: + IF cod = 256 THEN name von fremdstation + ELIF cod > 256 + THEN + taskinfo fremd + ELSE + task id von fremd + FI. + +taskinfo fremd: sendung starten (q, collector, cod-256, -8). + +task id von fremd: sendung starten (q,collector, zielstation,-6) . + +name von fremdstation: + BOUND TASK VAR tsk := vdr; + TASK VAR tsk1 := tsk; + forget (vdr); + vdr := nilspace; + sendung starten (q, tsk1, -7). + +zielstation: cod. + +END PROC neue sendung; + +PROC zeitueberwachung + (INT VAR snr, TASK VAR q, z, INT VAR ant,DATASPACE VAR dr): + snr INCR 1; + FOR strom FROM snr UPTO maxstrom REP zeitkontrolle PER; + snr := 0. + +zeitkontrolle: + IF vx.strom <> 0 AND zeit(strom) > 0 + THEN + zeit(strom) DECR 1; + IF sendung noch nicht zugestellt + THEN + IF zeit(strom) = 0 THEN + report ("Nicht zustellbar. """+nam (vx.ziel)+""". "+ + text (vx.rechnernummernDIV256)); + loesche verbindung (strom) + ELSE + snr := strom; + q := vx.quelle; + z := vx.ziel; + ant := vx.sendecode; + dr := vdr; + LEAVE zeitueberwachung + FI + ELIF zeit(strom) = 0 THEN wiederholen FI + FI. + +sendung noch nicht zugestellt: + typ (strom) = zustellung. + +wiederholen: + IF sendeeintrag + THEN + sendung wiederholen + ELSE + empfangseintrag freigeben + FI. + +sendeeintrag : vx.rechnernummern DIV 256 = own . + +sendung wiederholen: + IF wiederholung noch sinnvoll + THEN + IF frisch + THEN + time out bei open + ELSE + datenteil wiederholen + FI + ELSE + sendung loeschen + FI. + +wiederholung noch sinnvoll: + task noch da AND bei call noch im call. + +task noch da: vx.quelle = collector OR exists (vx.quelle). + +bei call noch im call: + IF call aufruf + THEN + callee (vx.quelle) = vx.ziel + ELSE + TRUE + FI. + +frisch: vx.sequenz = -1. + +time out bei open: + IF vx.sendecode > -4 THEN open wiederholen ELSE nak an quelle senden FI. + +nak an quelle senden: + forget (vdr); vdr := nilspace; + BOUND TEXT VAR erm := vdr; + erm := "Station "+text(vx.rechnernummernMOD256)+" antwortet nicht"; + snr := strom; + q := collector; + z := vx.quelle; + ant := error nak; + dr := vdr; + sendung loeschen; + LEAVE zeitueberwachung . + +open wiederholen: + sendereport ("wdh open"); + zeit(strom) := 20; + openblock := vx; + openblock.head := stx open; + ab die post. + +datenteil wiederholen: + sendereport ("wdh data. sqnr "+text (vx.sequenz)); + senden . + +empfangseintrag freigeben: + IF antwort auf call + THEN + weiter warten + ELSE + empfangsreport ("Empfangseintrag freigegeben"); + empfang loeschen + FI. +antwort auf call: callee (vx.ziel) = vx.quelle. + +weiter warten: zeit (strom) := 200. + +END PROC zeitueberwachung; + +PROC sendereport (TEXT CONST txt): + report (text (strom)+":"+txt+". Absender: """+nam (vx.quelle)+ + """. Ziel "+text(vx.rechnernummernMOD256)); +END PROC sendereport; + +PROC empfangsreport (TEXT CONST txt): + report (text (strom)+":"+txt+". Empfnger: """ + +nam (vx.ziel)+""". Quelle "+text (vx.rechnernummernDIV256)); +END PROC empfangsreport ; + +PROC sendung loeschen: + IF callaufruf CAND alter call (tasknr (vx.quelle)) = strom + THEN + alter call (tasknr (vx.quelle)) := 0 + FI; + vx.strom := 0; + forget (vdr) +END PROC sendung loeschen; + +PROC empfang loeschen: + quit zaehler INCR 1; + IF callaufruf AND alter call (tasknr (vx.ziel)) = strom + THEN + alter call (tasknr (vx.ziel)) := 0 + FI; + forget (vdr); + vx.strom := 0 +END PROC empfang loeschen; + +PROC loesche verbindung (INT CONST nr): + strom := nr; + IF sendeeintrag + THEN + sendung loeschen + ELSE + gegenstelle zum loeschen auffordern; + empfang loeschen + FI. + +gegenstelle zum loeschen auffordern: + IF verbindung aktiv THEN quittieren (-loesche) FI. + +verbindung aktiv: vx.strom > 0. + +sendeeintrag: vx.rechnernummern DIV 256 = own . + +END PROC loesche verbindung; + +PROC weiter senden: + IF NOT alles raus + THEN + sequenz zaehlung; + IF neue seite THEN seitennummer eintragen FI; + senden + FI. + +sequenz zaehlung: + vx.sequenz INCR 1. + +neue seite: + (vx.sequenz AND packete pro seite minus 1) = 0. + +seitennummer eintragen: + dr page (strom) := vx.seiten nummer; + vx.seitennummer := next ds page (vdr, dr page (strom)). + + +END PROC weiter senden; + +PROC senden: + zeit(strom) := 3; + vorspann senden; + daten senden. + +vorspann senden: + openblock := vx; + blockout (workspace, 1, dr verwaltungslaenge, vorspannlaenge). + +daten senden: + blockout (vdr,dr page (strom),distanz,nutzlaenge). + +distanz: nutzlaenge* (vx.sequenz AND (packete pro seite minus 1)). + +END PROC senden; + +PROC naechste verbindung vorbereiten: + FOR strom FROM 1 UPTO maxstrom REP + UNTIL vx.strom = 0 PER; + IF vx.strom <> 0 THEN errorstop ("Verbindungsengpass") FI. +END PROC naechste verbindung vorbereiten; + +PROC sendung starten (TASK CONST quelle, ziel, INT CONST code): + sendung starten (quelle,ziel, station(ziel), code) +END PROC sendung starten; + +PROC sendung starten (TASK CONST quelle, ziel, INT CONST ziel station,code): + IF ziel station = own + THEN + report ("Irrlufer: Sendung an eigene Station. Absender:"""+ + nam (quelle)+"""."); + vx.strom := 0; + forget (vdr) + ELSE + openblock.ziel := ziel; + openblock.quelle :=quelle; + openblock.sendecode := code; + openblock.rechnernummern:= ziel station + own256; + alten call loeschen (quelle); + IF call oder ping pong + THEN typ (strom) := call pingpong; call merken + ELSE typ (strom) := send wait FI; + sendung neu starten + FI. + +call oder pingpong: openblock.ziel = callee (openblock.quelle). + +call merken: alter call (tasknr (quelle)) := strom. + +END PROC sendung starten; + +PROC sendung neu starten: + openblock.head:= stx open; + openblock.sequenz := -1; + openblock.seitennummer:= next ds page (vdr,-1); + openblock.strom := strom; + vx := open block; + zeit(strom) := 3; + ab die post; + vx.head:=code stx+256*(vorspannlaenge+nutzlaenge). + +END PROC sendung neu starten; . + +ab die post: + block out (work space,1, dr verwaltungslaenge,open laenge). + +PROC alten call loeschen (TASK CONST quelle): + IF alter call aktiv + THEN + INT VAR lstrom := strom; + vx:=openblock; + strom := alter call (tasknr (quelle)); + IF in ausfuehrungsphase + THEN + sendereport ("Call-Lschung vorgemerkt"); + loeschung vormerken + ELSE + report ("Call gelscht."""+nam(quelle)+""". Strom "+text(strom)); + loesche verbindung (strom) + FI; + strom := lstrom; + openblock := vx + FI. + +in ausfuehrungsphase: + typ(strom) = call im wait OR typ (strom) = call in zustellung. + +loeschung vormerken: + typ(strom) := call im abbruch; + alter call (tasknr (quelle)) := 0. + + + alter call aktiv: + alter call (tasknr (quelle)) > 0. + +END PROC alten call loeschen; + +PROC packet eingang + (TEXT CONST ft, INT VAR snr, TASK VAR q, z, INT VAR ant,DATASPACE VAR dr): + snr := 0; + vorspann holen; + IF NOT ring logik THEN daten teil FI. + +ring logik: FALSE. +# IF selbst quelle THEN daten aus puffer entfernen ; TRUE + ELIF NOT selbst ziel THEN weitergeben; TRUE + ELSE FALSE + FI. + +selbst quelle: openblock.rechnernummern DIV 256 = station (myself). + +selbst ziel: (openblock.rechnernummern AND 255) = own. +# +daten aus puffer entfernen: + IF code (t) > nutzlaenge + THEN + BOOL VAR dummy :=blockin (workspace, 1, drverwaltungslaenge, nutzlaenge) + FI. +# +weitergeben: + IF code (t) > nutzlaenge + THEN + IF NOT blockin (workspace, 2, 0, nutzlaenge) + THEN LEAVE test auf packeteingang FI; + FI; + out (stx+t); + blockout (workspace, 1, drverwaltungslaenge2, blocklaenge); + IF code (t) > nutzlaenge + THEN + blockout (workspace, 2, 0, nutzlaenge) + FI. +# +vorspann holen: + sync; + IF NOT blockin (workspace, 1, dr verwaltungslaenge2, block laenge) + THEN LEAVE packeteingang + FI. + + +blocklaenge: IF code t > nutzlaenge + THEN + vorspannlaenge-2 + ELSE + code t -2 + FI. + +sync: + TEXT VAR skipped:=ft , t :=""; + REP + skipped CAT t; + t := incharety (1); + IF t = "" THEN + report ("skipped",skipped); + LEAVE packet eingang + FI ; + INT VAR codet := code (t); + UNTIL blockanfang PER; + IF skipped <> stx THEN report ("skipped bei sync:", skipped) FI. + +blockanfang: + (skipped SUB length(skipped)) = stx + AND + (codet = datenpacketlaenge + OR codet = ack laenge OR codet = neue ack laenge OR code t = openlaenge). + +daten teil: + IF neue verbindung + THEN + verbindung bereitstellen + ELIF quittung + THEN + strom := ack packet.strom; + IF falsche stromnummer THEN report ("Strom falsch in Quittung"); + LEAVE datenteil FI; + IF vx.strom = 0 THEN LEAVE datenteil FI; + IF ackpacket.code >= ok THEN weiter senden + ELIF ackpacket.code = -von vorne THEN + sendereport ("Neustart"); + openblock := vx; + sendung neu starten + ELIF ackpacket.code = -wiederhole THEN back 16 + ELIF ackpacket.code = -loesche THEN fremdloeschung + ELIF ackpacket.code = -beende AND alles raus THEN strom abschliessen + FI + ELIF verbindung festgestellt + THEN + zeit(strom) := 200; + opti := vx; + datenpacket + ELSE + strom := maxstrom1; + vx:=openblock; + report ("Daten ohne Eroeffnung von " +text(vx.rechnernummernDIV256) + +" Sequenznr "+text(openblock.sequenz)); + daten aus puffer entfernen; + IF alles raus THEN quittieren (-beende) ELSE quittieren(-von vorne) FI + FI. + +verbindung bereitstellen: + IF openblock.ziel = collector OR station (openblock.ziel) = own + THEN + freie verbindungsnummer; + vdr := nilspace; + vx := open block; + zeit(strom) := 10; + quittieren falls genug pufferplatz; + vx.sequenz := 0 ; + IF loeschung vorgemerkt + THEN + loesche verbindung (strom) + ELSE + opti := vx; + abschluss testen + FI; + FI. + +loeschung vorgemerkt: typ(strom) = call im abbruch. + +strom abschliessen: + IF call aufruf THEN zeit(strom) := 80; ausfuehrungsphase merken + ELSE + vx.strom := 0; + forget (vdr) + FI. + +ausfuehrungsphase merken: typ(strom) := call in zustellung. + +back16: + datenraum etwas rueckspulen; + nicht sofort senden (* wegen vagabundierender Quittungen *). + +nicht sofort senden: zeit(strom) := 2. + +datenraum etwas rueckspulen: + sendereport ("etwas rueckgespult"); + INT VAR sk , vs :=-1; + dr page (strom) := -1; + INT VAR i; + FOR i FROM 1 UPTO vx.sequenz DIV packete pro seite - etwas REP + vs INCR packete pro seite; + dr page (strom) := next ds page (vdr, dr page (strom)) + PER; + vx.seiten nummer := next ds page (vdr, dr page (strom)) ; + vx.sequenz := vs. + +etwas: 3. + +fremdloeschung: + IF fremdrechner ok und sendung + THEN + IF typ (strom) = call in zustellung + THEN + typ (strom) := call im wait + ELSE + sendereport ("Sendung von Gegenstelle geloescht"); + sendung loeschen + FI + FI. + +fremdrechner ok und sendung: + (ackpacket.rechnernummern DIV 256) = (vx.rechnernummern AND 255). + + +quittieren falls genug pufferplatz: + IF quit zaehler > 0 THEN + quit zaehler DECR 1; + open quittieren; + block vorab quittieren + FI. + +open quittieren: quittieren (ok). +block vorab quittieren: quittieren (ok). + +quittung: code t <= neue ack laenge. + +neue verbindung: code t = open laenge. + +verbindung festgestellt: + FOR strom FROM maxstrom DOWNTO 1 REP + IF bekannter strom + THEN LEAVE verbindung festgestellt WITH TRUE FI + PER; + FALSE. + +bekannter strom: + vx.strom = vorspann.strom AND vom selben rechner. + +vom selben rechner: + vx.rechnernummern = vorspann.rechnernummern. + +daten: + IF NOT blockin (vdr, opti.seiten nummer, distanz, nutzlaenge) + THEN quittieren (-wiederhole); LEAVE packeteingang + FI; + sequenz zaehlung; + IF neue seite kommt + THEN + vx.seiten nummer := vorspann.seiten nummer + FI. + +datenpacket: + IF sendung wartet auf zustellung THEN auffrischen ELSE daten holen FI. + +sendung wartet auf zustellung: typ (strom) = zustellung. + +auffrischen: zeit (strom) := 100; daten aus puffer entfernen. + +daten holen: + IF opti.sequenz >= vorspann.sequenz AND opti.sequenz < vorspann.sequenz+100 + THEN + IF opti.sequenz <> vorspann.sequenz + THEN empfangsreport ("Sequenzreset von "+text(opti.sequenz)+" auf "+ + text (vorspann.sequenz)); + vx.sequenz := vorspann.sequenz; + vorabquittung regenerieren + FI; + quittieren(ok); + daten ; + abschluss testen + ELSE + empfangsreport ("Sequenzfehler: soll "+text(vx.sequenz)+" ist "+ + text(vorspann.sequenz)); + quittieren (-wiederhole); + daten aus puffer entfernen + FI. + +vorabquittung regenerieren: quittieren (ok). + +distanz: (opti.sequenz AND packete pro seite minus 1 ) * nutzlaenge. + +sequenz zaehlung: + vx.sequenz INCR 1. + +neue seite kommt: +(vx.sequenz AND packete pro seite minus1) = 0. + +freie verbindungsnummer: + INT VAR h strom :=0; + FOR strom FROM 1 UPTO maxstrom REP + IF vx.strom = 0 THEN h strom := strom + ELIF bekannter strom + THEN empfangsreport ("Reopen"); + quit zaehler INCR 1; + forget (vdr); + LEAVE freie verbindungsnummer + ELIF antwort auf call + THEN + typ (strom) := call pingpong; + forget (vdr); + LEAVE freie verbindungsnummer + FI + PER; + strom := h strom; + IF strom = 0 THEN + error stop ("Zuviele simulatane Verbindungen") + FI; + typ(strom) := send wait. + +antwort auf call: + openblock.sendecode >= 0 AND + call aufruf AND vx.quelle = openblock.ziel AND vx.ziel = openblock.quelle. + +abschluss testen: + IF neue seite kommt AND vx.seiten nummer = -1 + THEN + quittieren (-beende); + an ziel weitergeben + FI. + +an ziel weitergeben: + IF tasknummerfrage THEN taskfrage beantworten ;pufferplatz freigeben; + ELIF tasknamenfrage THEN name senden ;pufferplatz freigeben; + ELIF taskinfofrage THEN task info senden;pufferplatz freigeben; + ELSE senden + FI. + +pufferplatz freigeben: quitzaehler INCR 1. + +senden: + max 100 versuche; + snr := strom; + IF NOT callaufruf THEN typ (strom) := zustellung FI; + q := vx.quelle; + z := vx.ziel; + ant := vx.sendecode; + dr := vdr; + LEAVE packet eingang. + +tasknummerfrage:opti.sendecode = -6. + +tasknamenfrage: opti.sendecode = -7. + +taskinfofrage: opti.sendecode = -8. + +max 100 versuche: zeit(strom) := 100. + +taskfrage beantworten: + BOUND TEXT VAR tsk := vdr; + TEXT VAR save tsk := tsk; + forget (vdr); vdr := nilspace; + BOUND TASK VAR task id := vdr; + disable stop; + task id := task(save tsk); + IF is error THEN + clear error; enable stop; + forget (vdr); vdr := nilspace; + BOUND TEXT VAR errtxt := vdr; + errtxt := text(station(myself))+"/"""+save tsk+""" gibt es nicht"; + sendung starten (collector, opti.quelle, 2) + ELSE + enable stop; + sendung starten (collector, opti.quelle, 0) + FI. + +name senden: + forget (vdr); vdr := nilspace; + tsk := vdr; + disable stop; + tsk := nam (opti.ziel); + clear error; enable stop; + sendung starten (collector, opti.quelle, 0). + +task info senden: + BOUND INT VAR ti code := vdr; + INT VAR ti cd := ti code; + forget (vdr); vdr := nilspace; + FILE VAR task inf := sequential file (output,vdr); + head line (task inf,"Station "+text(own)); + task info (ti cd, task inf); + sendung starten (collector,opti.quelle,0). + +END PROC packet eingang; + +PROC quittieren(INT CONST code) : + quellrechner wird zielrechner; + ackpacket.code := code; + ackpacket.head := stx quit; + ackpacket.strom := vx.strom; + blockout (workspace,1,dr verwaltungslaenge, ack laenge). + +quellrechner wird zielrechner: + ack packet.rechnernummern := vx.rechnernummern DIV 256 + + own256. + +END PROC quittieren; + +END PACKET basic net; diff --git a/system/net/1.7.5/src/callee b/system/net/1.7.5/src/callee new file mode 100644 index 0000000..42d80da --- /dev/null +++ b/system/net/1.7.5/src/callee @@ -0,0 +1,14 @@ +PACKET callee DEFINES callee: + +TASK PROC callee (TASK CONST t): + IF im wait THEN trick 1 (t); trick 2 ELSE niltask FI. +im wait: (status(t) AND 3) = 2. +END PROC callee; + +PROC trick 1 (TASK CONST t): + INT VAR x := pcb(t,11), y:=pcb(t,12); +END PROC trick1; + +TASK PROC trick 2: TASK VAR calle; calle END PROC trick2; + +END PACKET callee; diff --git a/system/net/1.7.5/src/net inserter b/system/net/1.7.5/src/net inserter new file mode 100644 index 0000000..8cccedd --- /dev/null +++ b/system/net/1.7.5/src/net inserter @@ -0,0 +1,50 @@ + +{ Inserter fr EUMEL - Netz - Software; 04.12.83 + bercksichtigt EUMEL - Versionen 1.7.3 und 1.7.5, sowie Multi / Single } + + +INT VAR version :: id (0), cy :: 4; +IF online THEN head FI; + +IF ich bin multi THEN insert multi net + ELSE meldung an single +FI. + +ich bin multi : (pcb (9) AND 255) > 1. + +insert multi net : + IF version >= 173 THEN IF version < 175 THEN insert and say ("callee") FI; + insert and say ("net report/M"); + insert and say ("basic net"); + insert and say ("net manager/M") + ELSE versionsnummer zu klein + FI. + +meldung an single : + cursor (1, cy); + putline + ("Das EUMEL - Netz ist zur Zeit nur auf Multi - User - Versionen"); + putline ("installierbar !"). + +head : + page; + putline (" E U M E L - Netz - Inserter"); + put ("---------------------------------"). + +versionsnummer zu klein : + cursor (1, cy); + putline ("Netzsoftware erst ab Version 1.7.3 insertierbar !"). + +PROC insert and say (TEXT CONST name of packet): + IF online THEN cl eop (1, cy); + put ("Paket '" + name of packet + "' wird insertiert"); + line (2); + cy INCR 1 + FI; + insert (name of packet); +END PROC insert and say; + +PROC cl eop (INT CONST cx, cy) : + cursor (cx, cy); + out (""4"") +END PROC cl eop; diff --git a/system/net/1.7.5/src/net manager-M b/system/net/1.7.5/src/net manager-M new file mode 100644 index 0000000..0383211 --- /dev/null +++ b/system/net/1.7.5/src/net manager-M @@ -0,0 +1,302 @@ +PACKET net manager DEFINES start,stop,net manager,frei: +TEXT VAR stand := "Netzsoftware vom 02.09.85"; + (*Heinrichs *) + +LET + ack = 0, + nak = 1, + error nak = 2, + zeichen eingang = 4, + list code = 15, + fetch code = 11, + freigabecode = 29, + continue code = 100, + erase code = 14, + report code = 99, + + (* Typen von Kommunikationsstrmen *) + + send wait = 0, + zustellung = 1, + call pingpong = 2, + call im wait = 3, + call im abbruch = 4, + call in zustellung = 5; + +LET STEUER = + STRUCT ( + INT head, + rechner nummern, + strom, + INT sequenz, + seiten nummer, + TASK quelle,ziel, + INT sende code); + +LET INFO = STRUCT (STEUER steuer, INT typ); + +TASK VAR sohn; +INT VAR strom,c. + +vx: v.steuer. + +PROC frei (INT CONST stat,lvl): + DATASPACE VAR ds := nilspace; + BOUND STRUCT (INT x,y) VAR msg := ds; + msg.x := stat; msg.y := lvl; + INT VAR return; + call (/"net port", freigabecode, ds, return) ; + forget (ds) +END PROC frei; + +PROC net manager (DATASPACE VAR ds, INT CONST order, phase, TASK CONST + ordertask): + + IF order = report code + THEN + forget ("report",quiet); + copy (ds,"report"); + forget (ds) + ELSE + IF ordertask < myself + OR order = list code + OR order > continue code + THEN + IF order = list code + THEN + enable stop; + forget (ds); ds := old ("report"); + FILE VAR ff := sequential file (output,ds); + putline (ff,stand); + putline (ff,"Rechner "+text(station(myself))+" um "+time of day); + send (ordertask, ack, ds) + ELSE + free manager (ds,order,phase,order task) + FI + ELSE + errorstop ("nur 'list' ist erlaubt") + FI + FI +END PROC net manager; + +TASK VAR cd,stask; +ROW 255 INT VAR erlaubt; +INT VAR i; +FOR i FROM 1 UPTO 255 REP erlaubt (i) := 0 PER; + +PROC communicate: + enable stop; + INT VAR scode; + DATASPACE VAR dr := nilspace; + neuer start (quit max); +REP + forget (dr); + wait (dr, scode, stask); + cd := collected destination; + IF zeichen da OR zeit abgelaufen + THEN + packet + ELIF cd = myself + THEN + netz info und steuerung + ELSE + neue sendung (stask, cd, scode, dr) + FI +PER. + +zeichen da: scode < 0 . + +zeit abgelaufen: scode = ack AND cd = myself. + +packet: + TEXT VAR t := incharety; + INT VAR snr, ant,err; + TASK VAR quelle, ziel; + snr := 0; + REP + IF t = "" + THEN + zeitueberwachung (snr, quelle, ziel, ant, dr); + ELSE + packet eingang (t, snr, quelle, ziel, ant, dr); + FI; + IF snr > 0 + THEN + IF ant > 5 AND erlaubt(station (quelle)) < 0 + THEN unerlaubt + ELSE + send (quelle,ziel,ant,dr,err); + fehlerbehandlung ; + FI + FI + UNTIL snr = 0 OR zeichen da PER. + +fehlerbehandlung: + IF ok oder ziel nicht da THEN loesche verbindung (snr) FI. + +ok oder ziel nicht da: err=0 OR err=-1. + +netz info und steuerung: + IF scode = list code THEN list status + ELIF scode = erase code THEN strom beenden + ELIF scode = freigabe code AND stask = father THEN freigabelevel + ELSE forget (dr); ablehnen ("nicht mglich") + FI. + +freigabelevel: + BOUND STRUCT (INT stat,lvl) VAR lv := dr; + IF lv.stat > 0 AND lv.stat < 256 THEN erlaubt (lv.stat) := lv.lvl FI; + send (stask,ack,dr). + +unerlaubt: + report ("Fremdzugriff von "+text(station (quelle))+" auf "+nam(ziel) + +" code "+text(ant)); + loesche verbindung (snr). + +strom beenden: + BOUND TEXT VAR stromtext := dr; + INT VAR erase strom := int (stromtext); + forget (dr); + strom := erase strom; + IF falsche stromnummer THEN ablehnen ("Strom gibt es nicht") + ELSE + BOUND INFO VAR v := verbindung (strom); + IF + stask = father OR stask = vx.quelle OR stask = vx.ziel + THEN + loeschen + ELSE ablehnen ("Nur Empfnger/Absender darf lschen") + FI + FI. + +loeschen: + IF sendeeintrag THEN + IF callee (vx.quelle) = vx.ziel THEN absender warnen FI; + loesche verbindung (strom) + ELSE + IF callee (vx.ziel) = vx.quelle THEN warnen FI; + loesche verbindung (strom) + FI; + dr := nilspace; + send (stask,ack,dr). + +absender warnen: + dr := nilspace; + send(vx.ziel,vx.quelle,1,dr,err) . + +warnen: + dr := nilspace; +BOUND TEXT VAR errtxt := dr; errtxt:= "Station antwortet nicht"; +send (vx.quelle,vx.ziel,error nak, dr, err). + +falsche stromnummer: strom < 1 OR strom > max verbindungsnummer. +sendeeintrag: vx.rechnernummern DIV256 = station (myself). +END PROC communicate; + +PROC ablehnen (TEXT CONST t): + DATASPACE VAR vdr := nilspace; + BOUND TEXT VAR errtxt := vdr; + errtxt := t; + send (stask, error nak, vdr). +END PROC ablehnen; + +PROC stop: + disable stop; + end (task ("net port")); + end (task ("net timer")); + clear error; +END PROC stop; + +PROC list status: + + DATASPACE VAR ds := nilspace; + FILE VAR f:=sequential file (output, ds); + FOR strom FROM 1 UPTO max verbindungsnummer REP + BOUND INFO VAR v := verbindung (strom); + IF vx.strom <> 0 THEN info FI + PER; + send (stask, ack, ds). + +info: + put (f,"Strom "+text(strom)+" (sqnr"+text(vx.sequenz)+")"); + IF sendeeintrag THEN sendeinfo ELSE empfangsinfo FI; + line (f). + +sendeeintrag: vx.rechnernummern DIV 256 = station(myself) . + +sendeinfo: + IF v.typ = call im wait THEN put (f,"erwartet Antwort von") + ELIF v.typ = call in zustellung THEN put (f,"Ziel busy. Zielstation:") + ELIF v.typ = call im abbruch THEN put (f,"wird gelscht bei Antwort von") + ELSE put (f,"sendet an") + FI; + put (f,vx.rechnernummernMOD256); + put (f,". Absender ist """+nam (vx.quelle)+"""."). + +empfangsinfo: + IF v.typ = zustellung THEN + put (f,"Sendung noch nicht zustellbar") + ELSE + put (f,"empfngt von"); + put (f,vx.rechnernummernDIV256); + FI; + put (f,". Empfaenger ist """+nam (vx.ziel)+"""."). +END PROC list status; + + +PROC start (INT CONST chan): + c:=chan; + start +END PROC start; +INT VAR quitmax := 3; +PROC start (INT CONST chan,quit): + quitmax := quit; + c:=chan; + start +END PROC start; + +PROC start: +stop; +IF exists ("report") THEN forget ("report") FI; +FILE VAR s := sequential file (output,"report"); +putline (s," N e u e r S t a r t "+time of day); +begin ("net port",PROC net io, sohn); +TASK VAR dummy; +begin ("net timer",PROC timer,dummy); +define collector (sohn) +END PROC start; + +PROC timer: + disable stop; + REP + clear error; + DATASPACE VAR ds := nilspace; + pause (100); + send (sohn, ack, ds) + PER; +END PROC timer; + +PROC net io: + disable stop; + fetch ("report"); + commanddialogue (FALSE); + continue (c); + communicate; + TEXT VAR emsg := "++++++ "+error message +" Zeile "+text(errorline); + clear error; + report (emsg); + save ("report"); + end (myself) +END PROC net io; + +put ("Netzkanalnummer:"); get (c);line; +IF yes ("Ist der Netzkanal mit Flukontrolle verdrahtet") THEN + quit max := 10 +ELSE + quit max := 3 +FI; +END PACKET net manager; + + +start; global manager (PROC (DATASPACE VAR,INT CONST,INT CONST, TASK +CONST) net manager ) diff --git a/system/net/1.7.5/src/net report-M b/system/net/1.7.5/src/net report-M new file mode 100644 index 0000000..3ce67ff --- /dev/null +++ b/system/net/1.7.5/src/net report-M @@ -0,0 +1,29 @@ +PACKET net report DEFINES report: + +LET reportcode = 99; + +PROC report (TEXT CONST x): + report(x,"") +END PROC report; + +PROC report (TEXT CONST txt, info): + IF storage (old("report")) > 20 THEN forget ("report",quiet) FI; + reportfile := sequential file (output, "report"); + put (reportfile, date); + put (reportfile, time of day); + put (reportfile, txt); + INT VAR i; + FOR i FROM 1 UPTO length (info) REP + INT VAR z := code (infoSUBi) ; + IF z < 32 OR z > 126 + THEN put (reportfile,"%"+text(z)) + ELSE put (reportfile,infoSUBi) + FI + PER; + line (reportfile); + DATASPACE VAR net report := old ("report"); + send (father, report code , net report) +END PROC report; +FILE VAR reportfile; + +END PACKET net report; diff --git a/system/net/1.8.7/doc/netzhandbuch b/system/net/1.8.7/doc/netzhandbuch new file mode 100644 index 0000000..7083462 --- /dev/null +++ b/system/net/1.8.7/doc/netzhandbuch @@ -0,0 +1,2045 @@ +____________________________________________________________________________ + + +#on("b")##on ("u")# +#center#Betriebssystem E U M E L +#off ("u")# + + +#center#Netzsoftware + + + + +#off("b")# +#center#Lizenzfreie Software der +#on ("b")# + +#center#Gesellschaft für Mathematik und Datenverarbeitung mbH, +#center#5205 Sankt Augustin + + +#off("b")# +#center#Die Nutzung der Software ist nur im Schul- und Hochschulbereich für +#center#nichtkommerzielle Zwecke gestattet. + +#center#Gewährleistung und Haftung werden ausgeschlossen + + +____________________________________________________________________________ +#page# +#pagenr ("%",1)##setcount(1)##block##pageblock##count per page# +#headeven# +#center#EUMEL Netzbeschreibung +#center#____________________________________________________________ + +#end# +#headodd# +#center#Inhalt +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +Netz - % #right# GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#Netz - % +#end# + +#center#Inhalt + +#clear pos##lpos(1.0)##rpos(9.5)# +#table# + +1. Einleitung #topage("0")# + +Teil 1: Netz einrichten und benutzen #topage("1")# + + +1.1. Hardwarevoraussetzungen #topage("1.1")# +1.2. Einrichten des Netzes #topage("1.2")# +1.3. Benutzung des Netzes #topage("1.3")# +1.4. Informationsmöglichkeiten #topage("1.4")# +1.5. Eingriffsmöglichkeiten #topage("1.5")# +1.6. Fehlerbehebung im Netz #topage("1.6")# +1.7. Sicherheit im Netz #topage("1.7")# + + + +Teil 2: Arbeitsweise der Netzsoftware #topage("2")# + + +2.1. Die Netztask #topage("2.1")# +2.2. Protokollebenen #topage("2.2")# +2.3. Stand der Netzsoftware #topage("2.3")# + + + +Teil 3: Netz-Hardware-Interface #topage("3")# + + +3.1. Einführung #topage("3.1")# +3.2. Arbeitsweise des Netz-Hardware-Interfaces #topage("3.2")# +3.3. Netztreiber #topage("3.3")# +3.4. Prozedurschnittstelle des EUMEL-Netzes #topage("3.4")# + + + +Anhang #topage("A")# + + +1. Fehlermeldungen #topage("A.1")# +2. Literaturhinweise #topage("A.2")# +3. Index #topage("A.3")# + +#table end# +#clear pos# + +#page# +#pagenr ("%", 2)##setcount (1)##block##pageblock##count per page# +#headeven# +#center#EUMEL Netzbeschreibung +#center#____________________________________________________________ + +#end# +#headodd# +#center#Einleitung +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +Netz - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#Netz - % +#end# + +1. Einleitung + +#goalpage("0")# +Das EUMEL-Netz dient dazu, mehrere EUMEL-Rechner (sog. #ib#Station#ie#en) miteinan­ +der zu koppeln. Diese Kopplung wird vom Betriebssystem dazu benutzt, das Sen­ +dungskonzept [1] so auszudehnen, daß Tasks verschiedener Stationen einander +Datenräume zusenden können. Auf dem #ib#Sendungskonzept#ie# aufbauende Konzepte +nutzen daher automatisch das Netz aus: So ist es z.B. möglich + +- von einer Station aus auf einer anderen zu drucken, + +- in die Task PUBLIC einer anderen Station #ib#Datei#ie#en zu sichern (save), vorausge­ + setzt, daß PUBLIC dort ein #on("b")#free global manager#off("b")# ist, + +- auf einer anderen Station zu archivieren (z.B. wenn das eigene Archivlaufwerk + defekt ist oder ein anderes Format hat). + +Diese #ib#Netzversion#ie# kann ab EUMEL-Version 1.8.1 eingesetzt werden. + +Diese Netzbeschreibung besteht aus drei Teilen. In Teil 1 wird beschrieben, wie das +EUMEL-Netz benutzt und eingerichtet wird. Als Benutzer eines EUMEL- +Rechners, der vernetzt ist, ist nur dieser Teil der Netzbeschreibung für Sie wichtig. +Teil 2 erklärt die Funktionsweise der #ib#Netzsoftware#ie#, im dritten Teil wird die Schnitt­ +stelle für die Anpassung anderer #ib#Netzhardware#ie# definiert. + +Hinweis: + +Zur erstmaligen #ib#Installation#ie# des EUMEL-Netzes ist außer dieser Beschreibung noch +die Netzsoftware (auf Floppy) und die EUMEL-Netz-#ib#Installationsanleitung#ie#, die mit +der Software geliefert wird, notwendig. + +In der vorliegenden Netzbeschreibung wird das EUMEL-Netz möglichst "hardware +unabhängig" beschrieben. Wenn hardwareabhängige Beispiele gegeben werden, so +ist die dort beschriebene Hardware stets die #ib#Datenbox#ie#. +#pagenr ("%", 3)##setcount (1)##block##pageblock##count per page# +#headeven# +#center#EUMEL Netzbeschreibung +#cneter#____________________________________________________________ + +#end# +#headodd# +#center#Teil 1 : Netz einrichten und benutzen +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +Netz - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#Netz - % +#end# +#page# + +Teil 1: Netz einrichten und benutzen +#goalpage("1")# + + + +1.1. Hardwarevoraussetzungen +#goalpage("1.1")# + + +Zwei Stationen + +Sie können zwei #ib#Station#ie# miteinander vernetzen, wenn Sie dafür an jeder Station eine +#ib#V.24#ie#-#ib#Schnittstelle#ie# zur Verfügung stellen. + +Diese beiden Schnittstellen verbinden Sie mit einem Kabel zur #ib#Rechnerkopplung#ie# [2]. + + +Mehrere Stationen + +Wenn Sie mehr als zwei Stationen vernetzen wollen, stehen Ihnen zwei Konzepte zur +Verfügung: das Anlegen von #ib#Netzknoten#ie# bzw. das Verwenden eines #ib#Strang#ie#es. Die +Konzepte können gemischt eingesetzt werden. + +Ein Strang besteht aus einer Anzahl von #ib#Netzbox#ie#en (z.B. KHW-Box oder Ethernet­ +anschluß). + +Jede Box besitzt eine #ib#Schnittstelle#ie# (z.B. #ib#V.24#ie#) zum Anschluß an einen der Kanäle +1...15 der zugeordneten #ib#Station#ie# und eine weitere Schnittstelle zur #ib#Verbindung#ie# der +Boxen untereinander. + +Ein #ib#Knoten#ie# ist eine Station, bei der der Netzbetrieb über mehrere Kanäle läuft. + +Da die #ib#Netzsoftware#ie# pro #ib#Kanal#ie# eines Knotens eine Task generiert, ist das Knoten­ +konzept dem Strangkonzept hinsichtlich des #ib#Durchsatz#ie#es unterlegen. Preisgünstiger +ist jedoch das #ib#Knotenkonzept#ie#, weil dabei #ib#Netzbox#ie#en überflüssig werden. + +Beim Knotenkonzept wird eine #ib#Vermaschung#ie# nicht zur Optimierung benutzt (Ver­ +maschung heißt, daß eine #ib#Zielstation#ie# über verschiedene Knoten erreichbar ist). Daher +sollte man keine Vermaschung vorsehen. + +#ib#Nachbarn#ie# sind Stationen, die an denselben #ib#Netzstrang#ie# angeschlossen oder direkt +über ein #ib#V.24#ie#-Kabel verbunden sind. + +Bei der Entscheidung, welche Stationen man zu #ib#Knoten#ie# macht, sollte beachtet wer­ +den, daß (a) Stationen, zwischen denen hoher Verkehr besteht, Nachbarn werden und +daß (b) besonders leistungsfähige Rechner #ib#Knoten#ie#stationen sein sollten. +#page# + +1.2. Einrichten des Netzes +#goalpage("1.2")# + + +Hinweis: Dieses Kapitel ist nur für Systembetreuer wichtig. + +a) Legen Sie für die am Netz beteiligten Rechner #ib#Stationsnummer#ie#n fest (von 1 an + aufsteigend). + + Die Boxen haben ebenfalls Stationsnummern. Die Stationsnummern der Box und + des zugeordneten Rechners müssen übereinstimmen. + + +b) Holen Sie an jeder #ib#Station#ie# die Task #on("bold")#configurator#off("bold")# an ein Terminal und geben Sie + das Kommando #on("bold")##ib#define station#ie# (x)#off("bold")#, wobei #on("bold")#x#off("bold")# die gewählte Stationsnummer ist. + + Hinweis: Taskkommunikationen, die zu diesem Zeitpunkt laufen, führen zu feh­ + lerhaftem Verhalten. Dies liegt daran, daß durch #on("bold")#define station#off("bold")# alle + #ib#Task-Id#ie#'s geändert werden müssen, weil eine #ib#Task-Id#ie# u.a. die + Stationsnummer der eigenen Station enthält (siehe 1.3). TASK- + Variablen, die noch Task-Id's mit keiner oder falscher Stationsnum­ + mer enthalten, können nicht mehr zum Ansprechen einer Task ver­ + wendet werden. + + Beispiel: Der #ib#Spoolmanager#ie# [3] richtet beim Kommando #on("bold")#start#off("bold")# einen #ib#Worker#ie# ein + und merkt sich dessen #ib#Task-Id#ie# in einer TASK-Variablen, um sicher­ + zustellen, daß nur der Worker #ib#Datei#ie#en zum Drucken abholt. Wird jetzt + das Kommando #on("bold")# define station#off("bold")# gegeben, kann der Spoolmanager + seinen Worker nicht mehr identifizieren, weil der Worker eine neue + Task-Id erhalten hat. Man muß daher vor #on("b")#define station#off("b")# den Worker + löschen und ihn danach mit dem Kommando #on("bold")##ib#start#ie##off("bold")# im Spoolmanager + wieder neu einrichten. + + + Sinnvollerweise gibt man #on("bold")#define station#off("bold")# sofort nachdem man ein frisches System + vom Archiv geladen hat. + + Zum Anschluß einer #ib#Datenbox#ie# #ib#konfigurieren#ie# Sie mit dem Kommando #on("bold")##ib#configurate#ie##off("bold")# + den für das Netz vorgesehenen #ib#Kanal#ie# auf + + - transparent + - 9600 #ib#Baud#ie# (Standardeinstellung der Boxen) + - #ib#RTS/CTS#ie#-#ib#Protokoll#ie# + - großen Puffer + - 8 bit + - even parity + - 1 stopbit. + + Falls diese Einstellungen nicht alle angeboten werden, klären Sie mit Ihrem + Rechnerlieferanten, ob und wie diese Einstellungen erreicht werden können. + + Hinweis: Notfalls kann auf das #ib#RTS/CTS#ie#-Protokoll verzichtet werden, wenn der + Eingabepuffer der #ib#Station#ie# groß genug ist. Die Anzahl simultan laufen­ + der Netzkommunikationen ist dann auf + + puffergröße DIV 150 + + begrenzt (bei Z80, 8086: 3; bei M20: 10). + + Hinweis: Es können auch andere #ib#Baud#ie#raten (2400, 4800, 19200) an der Box + eingestellt werden. + + +c) Achten Sie bei der #ib#Verbindung#ie# von der Station zur #ib#Netzbox#ie# (bzw. zur Gegen­ + station bei einem Zweistationennetz ohne Boxen) darauf, daß neben den Emp­ + fangs- und Sendeleitungen auch die Leitungen RTS und CTS verdrahtet wer­ + den, also ein 5-poliges Kabel verwendet wird [2]. Die #ib#Pin-Belegung#ie# der Boxen + entspricht der eines Kabels zur Rechner-Rechner-Kopplung. + + Beispiel: + + Verbindung eines BICOS-Systems mit der Box: + + Stecker Stecker + Pin Pin + + 2 <---------> 3 + 3 <---------> 2 + 4 <---------> 5 + 5 <---------> 4 + 7 <---------> 7 + + +d) Richten Sie eine Task #on("bold")##ib#net#ie##off("bold")# unter #on("bold")#SYSUR#off("bold")# ein und legen Sie eine #ib#Datei#ie# #on("b")##ib#netz#ie##off("b")# an, die + Ihre #ib#Netzkonfiguration#ie# enthält, oder ändern Sie die mitgelieferte Datei ent­ + sprechend ab (siehe auch 1.5.).#goalpage("sperre")# + + + Dem bisherigen Netz entspricht eine Datei #on("b")#netz#off("b")# mit folgendem Inhalt: + + definiere netz; + routen (1,127,k); + starte kanal (k,1,x); + aktiviere netz. + + k: ihr netzkanal. + x: IF yes ("#ib#Flußkontrolle#ie#") THEN 10 ELSE 3 FI. + + + + Laden Sie die Datei #on("b")##ib#net install#ie##off("b")# vom Archiv #on("b")#net#off("b")# und übersetzen Sie diese. Je nach­ + dem, welche EUMEL-Version auf der Maschine installiert ist, werden die notwen­ + digen Programmdateien insertiert. + + Es sind dies + + net report + net hardware interface + basic net + net manager + + + Das Netz wird dabei gestartet. + + + Hinweis: Obwohl die Task #on("b")#net#off("b")# sich noch mit #on("bold")##ib#continue#ie##off ("bold")# an ein Terminal holen + läßt, sollte man dies nur kurzzeitig tun, da der Netzverkehr solange + blockiert ist. + + In der #ib#Datei#ie# #on("b")#netz#off("b")# sollte der #ib#Kanal#ie#, über den der meiste Verkehr erwar­ + tet wird, zuerst gestartet werden. Für ihn wird die Task #on("b")##ib#net port#ie##off("b")# gene­ + riert, für jeden weiteren Kanal wird eine Task #on("b")##ib#net port#ie# k#off("b")# (k=Kanal­ + nummer) generiert. +#page# + +1.3. Benutzung des Netzes +#goalpage("1.3")# + + +Zur Benutzung des Netzes stehen folgende Operatoren und Prozeduren zur Verfü­ +gung: + + + +TASK OP #ib#/#ie# (INT CONST station, TEXT CONST taskname) + +liefert die Task #on("bold")#taskname#off("bold")# von der #ib#Station#ie# #on("bold")#station#off("bold")#. + + +#ib#Fehlerfälle#ie#: + + - #ib(4)#Task "...." gibt es nicht#ie(4)# + + Die angeforderte Task gibt es auf der #ib#Zielstation#ie# nicht. + + - #ib(4)##ib#Collectortask#ie# fehlt#ie(4)# + + die Task #on("b")##ib#net port#ie##off("b")# existiert nicht (siehe 6). + + Hinweis: #on("b")#net port#off("b")# wird bei jedem Start des Netzes neu generiert und beim + Auftreten eines nicht vorhergesehenen #ib#Fehler#ie#s beendet. Die Feh­ + lermeldung steht im #on("b")##ib#report#ie##off("b")# (siehe 4). + + - #ib(4)#Station x antwortet nicht#ie(4)# + + Eine nicht vorhandene oder abgeschaltete Station wurde angesprochen. + + Hinweis: Dieser #ib#Fehler#ie# wird angenommen, wenn eine Überwachungszeit von + ca. 30 Sekunden verstrichen ist, ohne daß Station x die Taskidenti­ + fikation angeliefert hat. + + - #ib(4)#Station x gibt es nicht#ie(4)# + + #ib#Station#ie# x steht nicht in den #ib#Routentabelle#ie#n. + + Diese Meldung kann auch erscheinen, wenn Station x erst kürzlich an das Netz + angeschlossen wurde. Sie steht dann noch nicht in den Routentabellen (siehe + auch 5.3.). + + Beispiel: + + list (5/"PUBLIC") + + Die Dateiliste von PUBLIC der Station 5 wird angefordert. + + + +TASK OP #ib#/#ie# (INT CONST station, TASK CONST task) + +liefert + +station / name (task) + +Beispiel: + + list (4/public) + + +Fehlerfall: + + "......" #ib(4)#gibt es nicht#ie(4)# + + Auf der eigenen Station gibt es die Task #on("b")#task#off("b")# nicht. + Der Taskname wird auf der eigenen Station bestimmt, wenn es dort die Task + nicht gibt, führt dies zur obigen Fehlermeldung. + +Abhilfe: + + Statt list(4/public) das Kommando list (4/"PUBLIC") verwenden. + + + +INT PROC #ib#station#ie# (TASK CONST task) + +liefert die #ib#Stationsnummer#ie# der Task #on("bold")#task#off("bold")#. + +Beispiel: + + put (station (myself)) + + gibt die eigene Stationsnummer aus. + + + + +PROC #ib#reserve#ie# (TEXT CONST archivename, TASK CONST archivetask) + +dient dazu, das Archiv auf der #ib#Station#ie# #on("bold")#station#off("bold")# anzumelden. + +Beispiel: + + reserve ("std", 4/"ARCHIVE"); #ib#list#ie# (4/"ARCHIVE") + + gibt das Inhaltsverzeichnis der Archivfloppy im Laufwerk der Station 4 aus. + + Hinweis: Vergessen Sie bei solchen #ib#Querarchivierungen#ie# nicht die Stationsangabe + bei jedem einzelnen Archivkommando (z.B fetch ("xxx", #on("bold")#4/#off("bold")# + "ARCHIVE")). + + Hinweis: Querarchivieren ist langsam. Verwenden Sie es nur, wenn Sie Floppy­ + formate umsetzen wollen. + + + + +PROC #ib#free global manager#ie# + +dient dazu, die eigene Task über das Netz ansprechbar zu machen. Jede andere +Task im Netz kann dann die üblichen #ib#Manager#ie#aufrufe (#on("bold")##ib#save#ie##off ("bold")#, #on("bold")##ib#fetch#ie##off ("bold")#, usw.) an die +eigene Task machen, sofern diese nicht an ein Terminal gekoppelt ist. + +Die Task wird (wie bei #on("bold")#break#off ("bold")#) abgekoppelt und meldet sich in Zukunft mit #on("bold")#mainte­ +nance#off ("bold")# statt mit #on("bold")#gib kommando#off ("bold")#. + +Beispiel: + + An Station 4 ruft man in der Task "hugo" das Kommando #on("bold")#free global manager#off("bold")# + auf. Anschließend kann man von jeder Station aus z.B. #on("bold")#list (4/"hugo")#off ("bold")# usw. auf­ + rufen. + + + + +TEXT PROC #ib#name#ie# (TASK CONST t) + +Diese (schon immer vorhandene) Prozedur wurde dahingehend erweitert, daß der +Name einer auf einer anderen Station existierenden Task über Netz angefordert wird. + +Existiert die Task nicht, so wird #on("bold")##ib#niltext#ie##off ("bold")# geliefert. + +Hinweis: Die Prozedur #on("bold")##ib#exists#ie##off ("bold")# wurde nicht auf das Netz ausgedehnt, da sie in Situa­ + tionen eingesetzt wird, wo es auf eine sehr schnelle Antwort ankommt. + Daher liefert #on("bold")#exists#off ("bold")# für eine stationsfremde Task immer FALSE. Will man + wissen, ob eine solche Task existiert, verwende man die Abfrage + + #on("bold")#IF name (task) <> "" THEN ... #off ("bold")#. + +#ib#Fehlerfall#ie#: + + - #ib(4)#Station x antwortet nicht#ie(4)# + + - #ib(4)##ib#Station#ie# x gibt es nicht#ie(4)# + +#page# + +1.4. Informationsmöglichkeiten + +#goalpage("1.4")# + +In der Task #on("bold")#net#off("bold")# wird eine #ib#Datei#ie# #on("bold")##ib#report#ie##off("bold")# geführt, in der #ib#Fehlersituationen#ie# des Netzes +verzeichnet werden. Diese Datei kann in jeder anderen Task auf derselben Station mit +#on("bold")##ib#list#ie# (/"#ib#net#ie#")#off("bold")# angesehen werden. Eine Erklärung der wichtigsten Meldungen finden Sie +im Anhang. + +In jeder Task kann durch das Kommando #on("bold")##ib#list#ie# (/"#ib#net port#ie#")#off("bold")# eine Übersicht über die +momentan laufenden #ib#Netzübertragungen#ie# der eigenen #ib#Station#ie# erhalten werden (nur für +den #ib#Kanal#ie#, an dem #on("b")##ib#net port#ie##off("b")# hängt). Entsprechendes gilt für die weiteren Netports der +eigenen Station. + +Mit #on("bold")##ib#list#ie# (/"#ib#net list")#ie##off("bold")# erhält man die Informationen, die man mit #on("b")#list (/"net")#off("b")# und #on("b")##ib#list#ie##off("b")# auf +alle Netports bekommt, sofern #on("b")##ib#listoption#ie##off("b")# (siehe S. #topage("listop")#) beim Generieren des Netzes +aufgerufen wurde. Dieser Aufruf funktioniert auch bei fremden Stationen (z.B. #on("b")#list +(5/"net list")#off("b")#). + +#page# + +1.5. Eingriffsmöglichkeiten + +#goalpage("1.5")# + +- Jede Task kann #ib#Sende#ie(1,"ströme")#- und #ib#Empfangsströme#ie#, die bei #on("bold")#list (/"net port")#off("bold")# gemel­ + det worden sind und die eigene Task betreffen, abbrechen. Hierzu ist das Kom­ + mando #on("bold")##ib#erase#ie# ("x", /"#ib#net port#ie#")#off ("bold")# zu geben, wobei x die #ib#Stromnummer#ie# (aus dem #on("bold")#list#off ("bold")#) + ist. + Unberechtigte #ib#Löschversuche#ie# werden abgewiesen. + Von privilegierten Tasks aus können jedoch mit #on("b")##ib#erase#ie##off("b")# beliebige Ströme abge­ + brochen werden. + + +- Durch das Kommando #on("bold")##ib#start#ie##off("bold")# kann von der Task #on("b")##ib#net#ie##off("b")# aus das Netz neu gestartet + werden. Dies setzt eine gültige #ib#Datei#ie# #on("bold")#netz#off("bold")# voraus. Es wird ein #on("bold")##ib#run#ie##off("bold")# auf diese Datei + gegeben. Das Kommando #on("b")##ib#start#ie##off("b")# ist nur noch aus Kompatibilitätsgründen zum alten + Netz vorhanden. + + +- Durch das Kommando #on("bold")##ib#routen aufbauen#ie##off("bold")# in der Task #on("b")##ib#net#ie##off("b")# werden die #ib#Routentabelle#ie#n + neu aufgebaut. Dies kann notwendig werden, wenn eine neue #ib#Station#ie# ans Netz + angeschlossen wurde (#ib#Fehlermeldung#ie# '#ib(4)#Station x gibt es nicht#ie(4)#'). #on("bold")#routen aufbauen#off ("bold")# + muß zuvor auch an allen dazwischenliegenden #ib#Knotenstation#ie#en gegeben werden. + + #on("bold")#routen aufbauen#off ("bold")# erzeugt eine Task #on("b")##ib#router#ie##off("b")#, die sich an das Terminal koppelt (die + Task #on("b")#net#off("b")# koppelt sich ab) und ein #ib#Protokoll#ie# ausgibt. Sind die #ib#Route#ie#n aufgebaut, + beendet sich die Task #on("b")#router#off("b")# mit der Meldung #on("b")#fertig#off("b")#. Es werden nur Stationen + bearbeitet, die nicht #ib#gesperrt#ie# (siehe S. #topage("sperre")#), und für die keine festen Routen + vereinbart sind. Der Vorgang dauert ca. 5 Sek. pro nicht gesperrter Station und + #ib#Netzkanal#ie#. Die #ib#Route#ie#n werden in einem #ib#Datenraum#ie# #on("b")##ib#port intern#ie##off("b")# hinterlegt. + + +- Der Aufruf #on("bold")##ib#definiere netz#ie##off("bold")# leitet eine #ib#Netzdefinition#ie# in der #ib#Datei#ie# #on("bold")##ib#netz#ie##off("bold")# ein. Dabei + werden alle augenblicklichen Netzkommunikationen gelöscht. Die Tasks #on("b")##ib#net port#ie# + (k)#off("b")#, wobei #on("b")#k#off("b")# die #ib#Kanalnummer#ie# ist, und #on("b")##ib#net timer#ie##off("b")# werden gelöscht. + + Dieser Aufruf muß vor den Aufrufen von #on("bold")##ib#starte kanal#ie#, #ib#erlaube#ie#, #ib#sperre#ie#, #ib#routen#ie#, + #ib#aktiviere netz#ie# und #ib#list option#ie##off("bold")# erfolgen. + + +- PROC #ib#sperre#ie# (INT CONST a,z) + bewirkt, daß die Stationen #on("bold")#a#off("bold")# bis #on("bold")#z#off("bold")# keine Manageraufrufe an Tasks dieser Station + geben dürfen (Genauer gesagt werden sendecodes > 6 nicht weitergeleitet, son­ + dern ein errornak mit dem Text "#ib(4)#kein Zugriff auf Station#ie(4)#" zurückgeschickt). + + Dieser Aufruf muß vor dem ersten #on("bold")##ib#starte kanal#ie##off("bold")# erfolgen. + + +- PROC #ib#erlaube#ie# (INT CONST a,z) + bewirkt, daß die Stationen #on("bold")#a#off("bold")# bis #on("bold")#z#off("bold")# Manageraufrufe an Tasks dieser Station geben + dürfen. + + Dieser Aufruf muß vor dem ersten #on("bold")##ib#starte kanal#ie##off("bold")# erfolgen. + + Beispiel: Alle Stationen außer 8 und 10 sollen #ib#gesperrt#ie# sein: + + #ib#sperre#ie# (1,127); erlaube (8,8); erlaube (10,10) + + Hinweis: 127 ist z.Zt. die maximale #ib#Stationsnummer#ie(1," maximale")#. + + +- PROC #ib#routen#ie# (INT CONST a,z,k) + legt fest, daß die Stationen #on("bold")#a#off("bold")# bis #on("bold")#z#off("bold")# an #ib#Kanal#ie# #on("bold")#k#off("bold")# direkt angeschlossen sind. Sen­ + dungen dieser Stationen werden nur bearbeitet, wenn sie über diesen Kanal her­ + einkommen (siehe 1.7.). Fehlt für eine Station ein entsprechender Routenaufruf, so + darf sie über einen beliebigen #ib#Netzkanal#ie# angeschlossen sein. Dies wird dann von + #on("bold")##ib#routen aufbauen#ie##off("bold")# ermittelt. + + PROC routen (INT CONST a,z,k,zw) + legt fest, daß die Stationen #on("bold")#a#off("bold")# bis #on("bold")#z#off("bold")# indirekt über die #ib#Knotenstation#ie# #on("bold")#zw#off("bold")# angeschlos­ + sen sind, und #on("b")#zw#off("b")# am Kanal #on("bold")#k#off("bold")# hängt. + + +- PROC #ib#starte kanal#ie# (INT CONST k,m,q) + startet eine #ib#Netztask#ie# am #ib#Kanal#ie# #on("bold")#k#off("bold")# im Modus #on("bold")#m#off("bold")# [4]. Dabei wird mit #on("bold")#q#off("bold")# die Anzahl + paralleler #ib#Empfangsströme#ie# festgelegt. Dadurch kann erreicht werden, daß der + #ib#Empfangspuffer#ie# nicht überläuft, indem nicht mehr als #on("b")#q#off("b")# Ströme quittiert werden. + Bei #ib#V.24#ie#-#ib#Schnittstelle#ie#n gebe man 3 (ohne #ib#Flußkontrolle#ie#) bzw. 10 (mit Flußkon­ + trolle) an. + + +- PROC #ib#aktiviere netz#ie# + muß als Abschluß in der Datei #on("bold")##ib#netz#ie##off("bold")# aufgerufen werden. Dabei wird die Task vom + Terminal abgekoppelt. Falls es bei #on("bold")##ib#definere netz#ie##off("bold")# den #ib#Datenraum#ie# #on("b")##ib#port intern#ie##off("b")#, der + die #ib#Route#ie#n enthält, nicht gab, wird #on("bold")##ib#routen aufbauen#ie##off("bold")# aufgerufen. + + +- PROC #ib#listoption#ie##goalpage("listop")# + erzeugt eine Task #on("b")##ib#net list#ie##off("b")#, die bei #on("bold")#list#off("bold")# den #ib#Fehlermeldung#ie#sreport und den Zustand + aller Netports liefert. Diese Task ist auch über Netz ansprechbar. In der Regel + sollte man #on("b")#listoption#off("b")# in der Datei #on("b")#netz#off("b")# aufrufen, es sei denn, das System ist sehr + klein. + +#page# + +1.6. #ib#Fehlersuche#ie# im Netz + +#goalpage("1.6")# + +#ib#Fehler#ie# im Netz können sich verschiedenartig auswirken. Im folgenden wird auf einige +Beispiele eingegangen: + +Beispiel: + + Auf #on("bold")#list (4/public)#off("bold")# erfolgt die Meldung '#ib(4)#Station#ie(4, " x antwortet nicht")# 4 antwortet nicht'. + + +#ib#Fehler#ie#möglichkeiten: + + - #ib#Station#ie# 4 ist nicht eingeschaltet. + Abhilfe: Station 4 einschalten. Kommando erneut geben. + + + - #ib#Netztask#ie# an Station 4 ist nicht arbeitsfähig. + Abhilfe: Kommando #on("bold")##ib#start#ie##off ("bold")# in der Task "net" auf Station 4. + + + - Stationsnummern und Boxnummern stimmen nicht überein. + Abhilfe: Mit #on("bold")#define station#off ("bold")# #ib#Stationsnummer#ie#n korrigieren (siehe 3.2). + + + - #ib#Verbindung#ie# Rechner/Box am eigenen Rechner oder an Station 4 fehlt. + Abhilfe: Verbindungen überprüfen. Durch Ansprechen einer dritten Station + kann oft schnell geklärt werden, welche Rechner/Box-Verbindung + defekt sein muß. + + + - Verbindung der Boxen untereinander defekt. + Abhilfe: Fehlende Verbindung, #ib#Masseschluß#ie# und #ib#Dreher#ie# (keine 1:1 Verbin­ + dung) überprüfen und beheben. + + Hinweis: Liegt z.B. ein Masseschluß vor, so kann es durchaus sein, daß + Boxen, die nicht in der Nähe des Masseschlusses stehen, noch + miteinander arbeiten können. Man kann aus der Tatsache, daß zwei + Boxen miteinander arbeiten können, also nicht schließen, daß man + nicht nach diesem Fehler suchen muß. + + + +Beispiel: + + Auf #on("bold")#list (4/public)#off("bold")# erfolgt keine Reaktion. + + + - Station 4 ist während dieser Sendung zusammengebrochen. + Abhilfe: Station 4 wieder starten. Die Bearbeitung des #on("bold")##ib#list#ie##off ("bold")#-Kommandos wird + automatisch wieder aufgenommen. + + + - PUBLIC auf Station 4 ist nicht im Managerzustand. + Abhilfe: PUBLIC in den Managerzustand versetzen. + + + - #ib#Fehler#ie# in der #ib#Netzhardware#ie#. + Überprüfen Sie, ob + + - die Boxen eingeschaltet sind, + - die Bereitlampe blinkt (wenn nicht: #ib#RESET#ie# an der Box), + - die #ib#V.24#ie#-Kabel richtig stecken, + - die Boxen untereinander verbunden sind (1 zu 1 Verbindungen der 5 poli­ + gen Diodenbuchsen). + + + - Fehler bei der #ib#Netzinstallation#ie#. + Überprüfen Sie, ob + + - alle Stationen an einem #ib#Strang#ie# gleiche oder kompatible Netzmodi einge­ + stellt haben [4], + - alle Stationen an einem #ib#Netzstrang#ie# auf die gleiche #ib#Nutzdatenlänge#ie# einge­ + stellt sind, + - bei der #ib#Kommunikation#ie# über #ib#Knoten#ie# alle Stationen die gleiche Nutzdaten­ + länge bei indirekten Sendungen eingestellt haben, + - die #ib#Route#ie#n auf allen beteiligten Stationen korrekt eingestellt sind. + + + +Beispiel: + + Auf #on("bold")#list (4/public)#off("bold")# erfolgt die Meldung '#ib(4)##ib#Collectortask#ie# fehlt#ie(4)#'. + + - Das Kommando #on("b")##ib#start#ie##off("b")# (bzw #on("b")##ib#aktiviere netz#ie##off("b")# in der #ib#Datei#ie# #on("b")#netz#off("b")#) wurde nicht gege­ + ben. Somit existiert #on("b")##ib#net port#ie##off("b")# nicht. + Abhilfe: Kommando #on("bold")#start#off ("bold")# in der Task #on("b")#net#off("b")# geben. + + + - Die #ib#Netzsoftware#ie# ist auf einen nicht vorhergesehenen #ib#Fehler#ie# gelaufen. Dieser + wird im #ib#Report#ie# vermerkt. #on("b")##ib#net port#ie##off("b")# wird dabei gelöscht. + Abhilfe: Geben Sie in der Task #on("bold")#net#off("bold")# das Kommando #on("bold")#start#off("bold")#. Dadurch wird die + Netzsoftware neu gestartet. Alle Netzkommunikationen dieser Station + gehen verloren. + + + +Beispiel: + + Nach #on("bold")##ib#fetch#ie# ("hugo",4/public)#off("bold")# sind Teile der Datei "hugo" verfälscht. + + - Die #ib#V.24#ie#-#ib#Verbindung#ie# zur Box ist nicht in Ordnung. + Abhilfe: Abstand zwischen Rechner und Box verkürzen; #ib#Baud#ie#rate ernie­ + drigen; durch Wechseln der #ib#V.24#ie#-#ib#Schnittstelle#ie# feststellen, ob diese + defekt ist. + Hinweis: Die Verbindung zwischen den Boxen ist durch #ib#Prüfsummen#ie# abge­ + sichert (Hardware). + +#page# + +1.7. Sicherheit im Netz + +#goalpage("1.7")# + +Bei Benutzung eines Rechnernetzes tauchen neue #ib#Sicherheitsprobleme#ie# auf. Um sie +verstehen und eingrenzen zu können, muß man sich mit dem #ib#Sicherheitskonzept#ie# des +Betriebssystems EUMEL vertraut machen: + +Eine Task im EUMEL kann nur manipuliert werden, wenn man sie entweder an ein +Terminal koppelt oder ihr Sendungen zustellt. + +Das Ankoppeln kann über #ib#Paßwort#ie# abgesichert werden. Nach dem Ankoppeln kann +die Task außerdem selbst bestimmen, wie sie die dann möglichen Eingaben behan­ +delt. So kann z.B. noch ein komplizierter Paßalgorithmus zu durchlaufen sein, bis +man auf einer offenen Programmierumgebung landet. + +Sendungen können eine Task auch nur mit ihrem Einverständnis beeinflussen, da +eine Sendung nur zugestellt wird, wenn die Task in der Prozedur #on("b")##ib#wait#ie##off("b")# steht. Insbe­ +sondere kann die Task den Absender einer Sendung überprüfen und gewisse Opera­ +tionen nur bei gewissen Absendern zulassen. So lehnt ein #on("b")##ib#global manager#ie##off("b")# z.B. alle +Dateimanagerkommandos ab, die nicht von Nachkommen (z.B. Söhnen) der Task +kommt. #on("b")##ib#free global manager#ie##off("b")# hingegen läßt Operationen wie #on("b")##ib#save#ie##off("b")# oder #on("b")##ib#erase#ie##off("b")# von +beliebigen Tasks, auch von fremden #ib#Station#ie#en, zu. Will man nur bestimmte Fremd­ +stationen zulassen, kann man z.B. folgendes Schema verwenden: + + PROC my #ib#manager#ie# + (DATASPACE VAR ds, INT CONST code, phase, TASK CONST source): + + IF station (source) = station (myself) OR station (source) = 10 + THEN + free manager (ds, code, phase, source) + ELSE + errorstop ("kein Zugriff") + FI + + END PROC my manager; + + global manager (PROC my manager) +#page# +Hier werden nur #on("b")#save#off("b")# usw. von Tasks der eigenen Station und der Station 10 zuge­ +lassen. Der Rest erhält die #ib#Fehlermeldung#ie# "kein Zugriff". + +Dieses Verfahren gewährt nur dann Sicherheit, wenn es nicht möglich ist, daß eine +beliebige Station sich als Station 10 ausgibt. + +Damit das Netz diese Sicherheit garantieren kann, müssen natürlich gewisse phy­ +sische Voraussetzungen erfüllt sein. Wenn z.B. die Station 10 über eine #ib#V.24#ie# ange­ +schlossen ist, aber jeder die Möglichkeit hat, an diese #ib#Schnittstelle#ie# seinen eigenen +Rechner anzuschliessen, dann kann das Netz natürlich nicht erkennen, ob es mit der +echten Station 10 verkehrt. + +Es muß also sichergestellt sein, daß an Kanälen für das Netz nicht manipuliert werden +kann. Bei einem #ib#Strang#ie# (Anschluß über #ib#Netzbox#ie#en) heißt das für die Boxen, daß sie +nur #ib#Telegramm#ie#e weitervermitteln, die die eingestellte #ib#Quellstationsnummer#ie# enthalten. +Sonst könnte jemand, der an denselben Strang wie #ib#Station#ie# 10 angeschlossen ist, +#ib#Telegramm#ie#e erzeugen, die so aussehen, als kämen sie von 10. + +Die #ib#Netzsoftware#ie# ihrerseits darf nur Telegramme auswerten, die über die richtige +#ib#Route#ie# (#ib#Kanal#ie# und #ib#Knotenstation#ie#) einlaufen. + +Leider hat dies die unangenehme Konsequenz, daß man automatisches Aufbauen und +Ändern von Routen verbieten muß, wodurch die Wartung der #ib#Netzkonfiguration#ie# +erschwert wird. + +Diese Version der #ib#Netzsoftware#ie# bietet den folgenden Kompromiß an: Nur für sicher­ +heitsrelevante #ib#Stationen#ie(1,", sicherheitsrelevante")# (im Beispiel Station 10) muß in der #ib#Datei#ie# #on("b")##ib#netz#ie##off("b")# die Route +angegeben werden. Dies muß in allen Stationen geschehen, für die die Station +sicherheitsrelevant ist, und in allen #ib#Knoten#ie# dazwischen. + +Für nicht sicherheitsrelevante Stationen werden #ib#Routeninformationen#ie# automatisch +aufgebaut und geändert. + +Hinweis: +Man wird oft ohne sicherheitsrelevante Stationen auskommen, indem man auf Ebenen +oberhalb der Netzebene Paßwortkontrollen einführt. So ist es z.B. ja möglich, Dateien +durch Paßworte zu schützen. Ein weiteres Beispiel ist ein #ib#Printerserver#ie#, der nur +ausdruckt, wenn eine mitgegebene Abrechnungskennung stimmt. Dabei ist es sogar +wünschenswert, daß die #ib#Station#ie# irrelevant ist, die den Druckauftrag gibt. +#pagenr ("%",21)##setcount (1)##block##pageblock##count per page# +#headeven# +#center#EUMEL Netzbeschreibung +#center#____________________________________________________________ + +#end# +#headodd# +#center#Teil 2 : Arbeitsweise der Netzsoftware +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +Netz - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#Netz - % +#end# +#page# + +Teil 2: Arbeitsweise der Netzsoftware +#goalpage("2")# + + + +2.1. Die Netztask +#goalpage("2.1")# + + +In diesem Kapitel wird beschrieben, wie eine #ib#Netztask#ie# in das System eingebettet ist +und welche Aufgaben sie hat. Unter Einhaltung dieser Konzepte kann die ausgeliefer­ +te Netzsoftware so geändert werden, daß sie beliebige andere #ib#Netzhardware#ie# unter­ +stützt. Die Netzsoftware ist so gegliedert, daß i.allg. nur eine hardwareabhängige +Komponente ausgetauscht werden muß (siehe Teil 3). + +Die Kommunikation zwischen Tasks im EUMEL-Betriebssystem basiert auf einem +#ib#Rendezvouskonzept#ie#: Die #ib#Zieltask#ie# einer Sendung muß empfangsbereit sein, wenn die +#ib#Quelltask#ie# sendet. + +Die Kommunikationsprozeduren auf der niedrigsten Ebene sind #on("bold")##ib#send#ie##off ("bold")# (Senden) und +#on("bold")##ib#wait#ie##off ("bold")# (Warten auf Empfang). Bei der Kommunikation werden ein Integer #on("bold")#code#off ("bold")# und ein +#ib#Datenraum#ie# #on("bold")#dr#off ("bold")# übergeben. #on("bold")#code#off ("bold")# muß >= 0 sein, da negative Codes systemintern ver­ +wandt werden. Ist die empfangende Task an einen #ib#Kanal#ie# gekoppelt (#on("bold")##ib#continue#ie##off ("bold")#), so +führt eine Zeicheneingabe auf diesem Kanal dazu, daß eine Sendung mit dem Code +-4 ankommt. Die Eingabedaten müssen mit den üblichen #ib#Eingabeprozeduren#ie# (#on("bold")##ib#inchar#ie##off ("bold")# +usw.) abgeholt werden. Der übermittelte #ib#Datenraum#ie# und die Absendertask sind dabei +ohne Bedeutung und dürfen nicht interpretiert werden. + +Die Prozedur #on("bold")#send#off ("bold")# hat einen #ib#Rückmeldeparameter#ie#, der besagt, ob die Sendung +übermittelt wurde. Gibt es die Zieltask nicht oder steht sie nicht im #on("bold")#wait#off ("bold")#, so kann die +Sendung nicht übermittelt werden. + +Ein Entwicklungskriterium für das EUMEL-Netz war es, möglichst wenig Unterstüt­ +zung von der virtuellen EUMEL-Maschine (#ib#EUMEL0#ie#) zu fordern, damit weitgehend in +ELAN programmiert werden kann. Dadurch ist es möglich, eine (privilegierte) Task mit +der Netzabwicklung zu betrauen. +#page# +Zunächst wird auf die #ib#EUMEL0#ie#-Unterstützung eingegangen: + +a) Es gibt die Prozedur #on("bold")##ib#define collector#ie##off ("bold")#, mit der die für das Netz verantwortliche + Task der EUMEL0-Maschine bekannt gemacht wird. Diese Task wird im fol­ + genden #ib#Collector#ie# genannt. + +b) Es gibt die Prozedur #on("bold")##ib#define station#ie##off ("bold")#, die für den Rechner eine #ib#Stationsnummer#ie# + einstellt. Anhand dieser Nummer werden die Rechner eines Netzes unterschie­ + den. Das Einstellen bewirkt, daß für alle Tasks die Stationsnummer in ihre + #ib#Task-Id#ie# eingetragen wird (Task-Id's sind die Werte, die der Typ TASK anneh­ + men kann). + +c) Der Befehl #on("bold")##ib#station#ie# (task)#off ("bold")# liefert die Stationsnummer der #on("bold")#task#off ("bold")#. So liefert z.B. + #on("bold")##ib#station#ie# (myself)#off ("bold")# die #ib#Stationsnummer#ie# des eigenen Rechners. + +d) Eine Sendung, deren #ib#Zieltask#ie# auf einem anderen Rechner liegt (also station (ziel) + <> station (myself)), wird auf die #ib#Collectortask#ie# geleitet. + +e) Es gibt eine Prozedur #on("bold")##ib#collected destination#ie##off ("bold")#, die es dem Collector erlaubt, die + eigentliche Zieltask einer auf ihn geleiteten Sendung zu erfahren. + +f) Es gibt eine Variante der Prozedur #on("bold")##ib#send#ie##off ("bold")#, die es dem Collector gestattet, der + #ib#Zieltask#ie# eine andere Task als Absender vorzutäuschen. + +g) Es gibt eine spezielle #ib#Task-Id#ie# #on("bold")##ib#collector#ie##off ("bold")#, durch die der augenblicklich eingestell­ + te #ib#Collector#ie# erreicht wird. Diese wird als Zieltask beim Aufruf der Vermittlungs­ + dienste angegeben (siehe S. #topage("collector")#). Eine Sendung an #on("bold")#collector#off ("bold")# wird von EUMEL0 + an den derzeitig eingestellten Collector geschickt. + +Ein Collector kann also auf drei Wegen von den übrigen Tasks desselben Rechners +Sendungen erhalten: + + 1. Über ein normales #on("b")#send#off("b")# (z.B. bei #on("bold")#list (/"net port")#off ("bold")#, wenn #on("b")#net port#off("b")# der derzeitige + #ib#Collector#ie# ist), + + 2. über ein #on("b")#send#off("b")# an die Task #on("bold")#collector#off ("bold")# (s.u.) und + + 3. als umgeleitete Sendung (z.B. bei #on("bold")#list#off ("bold")# an eine Task auf einem anderen + Rechner). + +Der Collector kann diese Fälle anhand von #on("bold")#collected destination#off ("bold")# unterscheiden. + +Die Punkte d) bis f) dienen dazu, den Collector für über Netz kommunizierende Tasks +unsichtbar zu machen: Der Collector taucht nicht als Ziel oder #ib#Quelle#ie# von Sendungen +auf. Das ist notwendig, damit normale Tasks sich nicht darum kümmern müssen, ob +eine Sendung übers Netz geht oder im eigenen Rechner bleibt. + +Wenn ein #ib#Datenraum#ie# an einen anderen Rechner geschickt wird, muß der gesamte +Inhalt (z. Zt. max. 1 MB) übertragen werden. Dies macht bei der üblichen Netzhard­ +ware eine Zerlegung in #ib#Paket#ie#e nötig [5]. Bei der Zerlegung eines Datenraumes in +Pakete (#ib#Telegramm#ie#e) gelten folgende Einschränkungen: + + - Ein Paket kann maximal eine #ib#Datenraumseite#ie# als #ib#Nutzdaten#ie# enthalten. + + - Die #ib#Nutzdatenlänge#ie# ist für einen #ib#Übertragungsweg#ie# konstant. + + - Alle Stationen eines #ib#Netzstrang#ie#s senden mit gleicher Nutzdatenlänge (#on("b")##ib#data + length#ie##off("b")#). + + - Bei indirekter #ib#Kommunikation#ie(1,"indirekte")# (über #ib#Knoten#ie#) muß die Nutzdatenlänge für in­ + direkte Verbindungen (#on("b")##ib#data length via node#ie##off("b")#) auf allen beteiligten Stationen + gleich eingestellt sein. + + +Für Netze stehen spezielle Blockbefehle zur Verfügung: + + +g) #ib#blockin#ie# / #ib#blockout#ie# (dr,seite,512+abstand,anzahl,rest) + + Es werden maximal #on("bold")#anzahl#off ("bold")# Bytes transferiert. In #on("bold")#rest#off ("bold")# wird zurückgemeldet, wie + viele Bytes nicht bearbeitet wurden (z.B. weil der #ib#Kanal#ie# nichts anliefert). Bear­ + beitet werden die Bytes + + #on("bold")#seite#off ("bold")# * 512 + #on("bold")#abstand#off ("bold")# + + bis maximal + + #on("bold")#seite#off ("bold")# * 512 + #on("bold")#abstand#off ("bold")# + #on("bold")#anzahl#off ("bold")# - 1 + + Der Kanal, an den die Task gekoppelt ist, wird dabei über #ib#Stream-IO#ie# (d.h. + #on("bold")##ib#incharety#ie##off ("bold")#, bei #on("bold")#blockin#off ("bold")# bzw. #on("bold")#out#off ("bold")# bei #on("bold")#blockout#off ("bold")#) angesprochen. + + Hinweis: Die Anforderung darf nicht über #ib#Seitengrenze#ie# gehen, d.h. + + #on("bold")#abstand#off ("bold")# + #on("bold")#anzahl#off ("bold")# <= 512 + + muß erfüllt sein. + + +Eine Netzsendung läuft wie folgt ab: + +Die Task q auf Rechner rq mache ein #on("bold")##ib#send#ie##off ("bold")# an die Task z auf Rechner rz. + +1. Die Prozedur #on("bold")#send#off ("bold")# ist ein #ib#EUMEL0#ie#-Befehl. Die EUMEL0-Ebene erkennt, daß die + Sendung an die #ib#Station#ie# rz geht, da die #ib#Stationsnummer#ie# in der #ib#Task-Id#ie# enthalten + ist. Daher wird die Sendung zum #ib#Collector#ie# umgeleitet, den EUMEL0 wegen der + Einstellung durch #on("bold")##ib#define collector#ie##off ("bold")# kennt, umgeleitet. + +2. Die Task Collector empfängt über #on("bold")##ib#wait#ie##off ("bold")# den #ib#Datenraum#ie#, den #ib#Sendecode#ie# und die + Absendertask q. Die #ib#Zieltask#ie# z erfährt sie durch #on("bold")##ib#collected destination#ie##off ("bold")#. + +3. Der Collector nimmt Kontakt mit dem Collector des Rechners #on("b")#rz#off("b")# auf, dessen Sta­ + tionsnummer ja #on("bold")##ib#station#ie#(z)#off ("bold")# ist, und übermittelt diesem Sendecode, #ib#Quelltask#ie# (q), + eigentliche Zieltask (z) und den #ib#Datenraum#ie#. Da die Collectoren in ELAN geschrie­ + ben sind, können sie an beliebige #ib#Netzhardware#ie# und #ib#Protokoll#ie#e angepaßt werden. + +4. Der #ib#Collector#ie# auf Rechner #on("b")#rz#off("b")# verwendet das spezielle #on("bold")#send#off ("bold")#, um der Zieltask die + Sendung zuzustellen. Dadurch erscheint nicht der Collector, sondern die Task #on("b")#q#off("b")# + als Absender der Sendung. + +Zur Abwicklung der #ib#Vermittlungsebene#ie# (siehe S. #topage("vermittlung")#) muß der Collector noch spe­ +zielle Funktionen beherrschen. Diese sind + + der #on("b")##ib#/#ie#-Operator#off("b")# (Taskname in #ib#Task-Id#ie# wandeln) und + die #on("b")##ib#name#ie##off("b")#-Prozedur (Task-Id in Namen wandeln). + +Der #on("b")#/#off("b")#-Operator macht eine Sendung an den #on("bold")##ib#collector#ie##off ("bold")#, wobei im #ib#Datenraum#ie# der Name +der Task steht und der #ib#Sendecode#ie# gleich der Stationsnummer ist (siehe [6] ). Der +#ib#Collector#ie# setzt sich mit dem Collector dieser Station in Verbindung, damit dieser die +Task-Id ermittelt und zurückschickt. Der eigene Collector schickt dann dem #on("b")#/#off("b")#-Oper­ +ator als Antwort einen Datenraum, der die #ib#Task-Id#ie# enthält. + +Umgekehrt läuft #on("bold")##ib#name#ie##off ("bold")# ab: Wenn die Task-Id von einer fremden Station ist, schickt +#on("bold")#name#off ("bold")# eine Sendung an den #on("bold")##ib#collector#ie##off ("bold")#, wobei im Datenraum die Task-Id steht und +Sendecode = 256 ist. Der Collector entnimmt die #ib#Stationsnummer#ie# der Task aus der +Task-Id und läßt sich vom entsprechenden Collector den Tasknamen geben. Dieser +wird der #on("bold")#name#off ("bold")#-Prozedur im Antwortdatenraum übergeben. + +Netztasks bauen sich #ib#Routentabellen#ie# auf (#ib#Datei#ie#name #on("b")##ib#port intern#ie##off("b")#). Aufgrund dieser +Tabellen weiß jede #ib#Netztask#ie#, über welchen #ib#Kanal#ie# und welche #ib#Nachbarstation#ie# eine +#ib#Zielstation#ie# erreichbar ist. Wenn der #ib#Collector#ie# einen Sendeauftrag erhält, prüft er, ob +die Zielstation über seinen Kanal erreichbar ist. Wenn nicht, leitet er Parameter und +#ib#Datenraum#ie# der Sendung an die geeignete Netztask weiter. +#page# + +2.2. Ebenen + +#goalpage("2.2")# + +In diesem Kapitel werden die #ib#Protokollebenen#ie# für das Netz beschrieben, wie sie die +ausgelieferte Netzsoftware benutzt und erwartet. Bei anderer Netzhardware als Daten­ +boxen müssen die Ebenen a) bis c) ausgetauscht werden [4]. Unter Einhaltung der im +vorigen Kapitel beschriebenen Randbedingungen können auch die höheren Ebenen +geändert werden. + + +a) Physikalische Ebene + + - #ib#Station#ie# <--> Box + + #ib#V.24#ie#-#ib#Schnittstelle#ie# mit #ib#RTS/CTS#ie#-Handshake. Vollduplex. + + - Box <--> Box + + #ib#RS422#ie# über 2 verdrillte Leitungspaare (Takt und Daten). + + +b) Verbindungsebene + + - Station <--> Box + + Asynchron + 8 Bit + Even Parity + 2400/4800/9600/19200 #ib#Baud#ie# einstellbar über Lötbrücken) + + - Box <--> Box + + #ib#SDLC#ie# + 400 KBaud +#page# +c) #ib#Netzebene#ie# +#goalpage("quelle")# + + - Station <--> Box + + #ib#Telegrammformat#ie#: #ib#STX#ie#, , , <#ib#quelle#ie#>, <(n-4) byte> + + ist #ib#Längenangabe#ie# ( 8 <= n <= 160) + , sind #ib#Stationsnummer#ie#n. Diese müssen an den jeweiligen + Boxen eingestellt sein. + + Box --> Station: + + Ein #ib#Telegramm#ie# kommt nur bei der #ib#Station#ie# an, bei deren Box die Nummer + eingestellt ist. Dadurch ist ein Mithören fremder #ib#Übertragung#ie# nicht + möglich (Datenschutz). + + Zwischen Telegrammen können #ib#Fehlermeldung#ie#en der Box (Klartext) übermittelt + werden (z.B. 'skipped x', wenn ein #ib#STX#ie# von der Box erwartet wurde, aber 'x' + von der Station ankommt). + + Station --> Box: + + Ein Telegramm wird nur abgeschickt, wenn <#ib#quelle#ie#> mit der eingestellten + Nummer übereinstimmt (Datenschutz: Man kann nicht vorschwindeln, eine + beliebige Station zu sein, es sei denn, man hat physischen Zugriff zur Box und + stellt dort die Stationsnummer um). + + - Box <--> Box + + #ib#Telegrammformat#ie#: + FRAME, , <#ib#quelle#ie#>, , + + Eine #ib#Längenangabe#ie# ist nicht nötig, da #ib#SDLC#ie# eine Rekonstruktion der Länge + erlaubt. + + Telegramme mit falschen #ib#CRC-Code#ie# werden vernichtet. Auf höheren Ebenen + muß dies durch #ib#Zeitüberwachung#ie# erkannt und behandelt werden. + +#page# +d) Transportebene + + Diese Ebene wickelt das Rendezvous zwischen einer Task, die #on("bold")##ib#send#ie##off ("bold")# macht, und + einer Task, die im #on("bold")##ib#wait#ie##off ("bold")# steht, ab [1]. + + Der im #on("bold")#send#off ("bold")# angegebene #ib#Datenraum#ie# wird als Folge von #ib#Seiten#ie# (im EUMEL- + Sinne: Pagingeinheit und Allokiereinheit) übermittelt, wobei jede Seite ggf. noch in + n Byte große Stücke zerlegt wird. Es werden nur echt allokierte Seiten übermit­ + telt. Um nicht jedes #ib#Telegramm#ie# voll qualifizieren zu müssen, wird zunächst eine + Art virtuelle #ib#Verbindung#ie# durch ein #ib#OPEN#ie#-Telegramm eröffnet. Danach folgen + variabel viele #ib#DATA#ie#-Telegramme. Beide Sorten werden durch #ib#QUIT#ie#-Tele­ + gramme quittiert, um folgende Funktionen zu ermöglichen: + + #ib#Flußkontrolle#ie# (z.B. Zielrechner langsam), + Wiederaufsetzen (verlorene Telegramme), + Abbruch (z.B. weil Zieltask inzwischen beendet). + + Ein #ib#CLOSE#ie#-Telegramm ist nicht nötig, da das letzte DATA-Telegramm als + solches erkannt werden kann (siehe unten). +#page# + - #ib#OPEN#ie#-Telegramm + +#clear pos# + 0 1 2 3 4 5 6 7 8 9. Byte ++------+------+------+------+-------------+-------------+-------------------+ +I STX I 24 I Ziel IQuelleI Endziel I Endquelle I Strom I ++------+------+------+------+-------------+-------------+-------------------+ + + 10 11 12 13 14 15 16 17 ++-------------+-------------+---------------------------+ +I Sequenz I Seite I Quelltask I ++-------------+-------------+---------------------------+ + + 18 19 20 21 22 23 ++---------------------------+-------------+ +I Zieltask I Code I ++---------------------------+-------------+ + + + + <#ib#ziel#ie#>, <#ib#quelle#ie#> siehe S. #topage("quelle")# + + <#ib#endziel#ie#> Eigentliche #ib#Zielstation#ie#. Ist = , so ist + das #ib#Telegramm#ie# angekommen. Andernfalls muß die Station + den #ib#Nachbarn#ie# zum Erreichen des als + neues einsetzen und das Telegramm an diesen + Nachbarn weiterleiten. + + <#ib#endquelle#ie#> Eigentliche #ib#Absenderstation#ie#. ist dagegen immer + die Nummer der sendenden #ib#Nachbarstation#ie#. + + <#ib#strom#ie#> Die #ib#Stromnummer#ie# identifiziert die virtuelle #ib#Verbindung#ie#. Sie + muß in den #ib#QUIT#ie#-Telegrammen angegeben werden. + + <#ib#sequenz#ie#> -1 (Kennzeichen für OPEN) + + <#ib#seite#ie#> Nummer der ersten echt allokierten #ib#Seite#ie# des #ib#Datenraum#ie#s + (=-1, falls Nilspace) + + <#ib#quelltask#ie#> #ib#Task-Id#ie# der sendenden Task + + <#ib#zieltask#ie#> Task-Id der empfangenden Task + + Wert des im #on("bold")##ib#send#ie##off ("bold")# angegebenen Codes +#page# + - #ib#DATA#ie#-Telegramm + + + + + + 0 1 2 3 4 5 6 7 8 9. Byte ++------+------+------+------+-------------+-------------+-------------------+ +I STX I LängeI Ziel IQuelleI Endziel I Endquelle I Strom I ++------+------+------+------+-------------+-------------+-------------------+ + + 10 11 12 13 14 ++-------------+-------------+-----------------------------------------------+ +I Sequenz I Seite I n Byte Daten (Länge = 14 + n) I ++-------------+-------------+-----------------------------------------------+ + + + <#ib#laenge#ie#> Gesamtlänge des Telegramms. + #on("b")#laenge#off("b")# = #on("b")##ib#nutzlaenge#ie##off("b")# + 14. + Für #on("b")#nutzlaenge#off("b")# sind nur die Werte 64,128,256 und 512 + zugelassen (siehe 1). #on("b")#laenge#off("b")# wird codiert dargestellt (siehe + Teil 3). + + + <#ib#sequenz#ie#> wird von Telegramm zu Telegramm hochgezählt. Sie dient + der Überwachung bzgl. verlorengegangener Telegramme + bzw. durch #ib#Zeitüberwachung#ie# verdoppelter Telegramme. + + <#ib#seite#ie#> Nummer der x-ten echt allokierten Seite des #ib#Datenraum#ie#s + (x = (( DIV anzahl pakete pro seite) + 2) + + #ib#Nutzinformation#ie#. Diese gehört zur #ib#Adresse#ie# a des Daten­ + raums. + + a = + N ( DIV anzahl pakete pro seite + 1) * 512 + + ( MOD anzahl pakete pro seite) * n + + wobei N (x) die Nummer der x-ten Seite und + n die #ib#Nutzdatenlänge#ie# ist. + + Aus den Formeln ergibt sich, daß diese Nummer schon in + einem vorhergehenden DATA/OPEN-Telegramm über­ + mittelt wurde (im Feld ). + + - #ib#QUIT#ie#-Telegramm + + + 0 1 2 3 4 5 6 7 8 9. Byte ++------+------+------+------+-------------+-------------+-------------------+ +I STX I 12 I Ziel IQuelleI Endziel I Endquelle I Strom I ++------+------+------+------+-------------+-------------+-------------------+ + + 10 11 ++-------------+ +I Quit I ++-------------+ + + + + <#ib#strom#ie#> muß die #ib#Stromnummer#ie# sein, die in dem #ib#OPEN#ie#/#ib#DATA#ie#­ + Telegramm stand, das quittiert wird. + + 0 : ok. Nächstes Telegramm schicken. + + -1: #ib#Übertragung#ie# neu starten (mit #ib#OPEN#ie#), weil die Emp­ + fangsstation das OPEN nicht erhalten hat. + + -2: Übertragung ca. 20 Telegramme zurücksetzen. + + -3: Übertragung abbrechen. + + -4: #ib#Quittung#ie# für letztes Telegramm einer Sendung. + + +e) #ib#Vermittlungsebene#ie##goalpage("vermittlung")# #goalpage("collector")# + + Diese Ebene ist dafür zuständig, Namen von Tasks auf anderen Stationen in + #ib#Task-Id#ie#'s (Werte des Typs TASK) zu wandeln und umgekehrt. Hierzu wird im + entsprechenden #ib#OPEN#ie#-Telegramm der Code -6 (bzw. -7) als ein­ + getragen. Die #ib#Netzempfangstask#ie# erkennt diese #ib#Codes#ie# und wickelt die Aufgaben + selbst ab, so daß es dabei nicht nötig ist, irgendeine Task-Id der #ib#Zielstation#ie# zu + kennen. + + Dieses Verfahren ist möglich, weil im #on("bold")##ib#send#ie##off ("bold")# nur positive Codes erlaubt sind. +#page# +f) #ib#Höhere Ebenen#ie# + + Höhere Ebenen sind nicht mehr netzspezifisch. Sie basieren alle auf dem Send/ + Wait-Konzept des EUMEL. So gibt es z.B. den #on("bold")##ib#global manager#ie##off ("bold")#, der Aufbewah­ + rung und Zugriff von #ib#Datei#ie#en in einer Task regelt. Dabei darf diese Task (bei der + Variante #on("bold")##ib#free global manager#ie##off ("bold")#) auf einer beliebigen #ib#Station#ie# im Netz liegen. Wegen + des #ib#Rendezvous-Konzept#ie#s können beliebige Sicherheitsstrategien benutzt werden + (z.B.: keine Dateien an Station 11 ausliefern). Von großem Wert ist z.B., daß + man ohne weiteres das Archiv (Floppylaufwerk) einer anderen Station anmelden + und benutzen kann, wodurch eine einfache Konvertierung von Floppyformaten + möglich ist. Dies ist möglich, weil auch die Archiv-Task der Stationen sich an + das Globalmanagerprotokoll halten. + + + + + +Bemerkungen + +#ib#Fehlerbehandlung#ie# besteht bis Ebene c) darin, fehlerhafte #ib#Telegramm#ie#e einfach zu +entfernen. Die Ebene d) überwacht den Netzverkehr sowieso über #ib#Timeout#ie#s, die eine +Wiederholung eines Telegrammes bewirken, wenn die #ib#Quittung#ie# ausbleibt. + +Da bei der sendenden #ib#Station#ie# der ganze #ib#Datenraum#ie# zur Verfügung steht, ist eine +#ib#Fenstertechnik#ie# (wie bei #ib#HDLC#ie#) nicht nötig. Es kann zu jedem Zeitpunkt um beliebig +viele Telegramme zurückgesetzt werden. + +Da im EUMEL eine #ib#Textdatei#ie# ein #ib#Datenraum#ie# mit sehr komplexer Struktur ist (wegen +der Insert/Delete-Möglichkeiten, ohne den Rest der #ib#Datei#ie# zu verschieben), ist es ein +hoher Aufwand, von einem fremden Betriebssytem aus eine Textdatei in das +EUMEL-Netz zu senden. Für solche Zwecke muß noch eine einfachere Dateistruktur +definiert und entsprechende Dateikonverter erstellt werden. +#page# + +2.3. Stand der Netzsoftware + +#goalpage("2.3")# + +Das EUMEL-System wickelt die Prozedur #on("bold")##ib#send#ie##off("bold")# über das Netz ab, wenn die Sta­ +tionsnummer der #ib#Zieltask#ie# ungleich der eigenen #ib#Stationsnummer#ie# ist. Umgekehrt kann +man der von der Prozedur #on("bold")##ib#wait#ie##off("bold")# gelieferten Absendertask die #ib#Absenderstation#ie# entneh­ +men (siehe Prozedur #on("bold")##ib#station#ie##off("bold")# in Teil 1). + +Anders als bei einem #on("bold")##ib#send#ie##off("bold")# innerhalb einer Station meldet ein #on("bold")#send#off("bold")# an eine Task einer +fremden Station immer 0 zurück (Task gibt es und Task war im wait), obwohl dies +nicht der Fall sein muß. Ist die Sendung vollständig zur Zielstation übertragen, so +versucht der dortige #ib#Collector#ie# diese hundertmal im Sekundenabstand zuzustellen. +Bleibt das erfolglos, wird die Sendung vernichtet. +#pagenr ("%", 33)##setcount (1)##block##pageblock##count per page# +#headeven# +#center#EUMEL Netzbeschreibung +#center#____________________________________________________________ + +#end# +#headodd# +#center#Teil 3 : Netz Hardware Interface +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +Netz - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#Netz - % +#end# +#page# + +Teil 3: Netz-Hardware-Interface + + +#goalpage("3")# + + +3.1. Einführung + + #goalpage("3.1")# + +In diesem Teil der Netzbeschreibung wird die #ib#Schnittstelle#ie# beschrieben, über die +#ib#Netzhardware#ie# (also #ib#Datenbox#ie#en, #ib#Netzbox#ie#en oder Netzkarten) an die EUMEL-Netz­ +Software angepaßt werden kann. Dieser Teil der Beschreibung ist also nur für Netz­ +implementatoren wichtig. + +Das EUMEL-Netz wurde dazu konzipiert, zwei oder mehr EUMEL-Rechner über +#ib#V.24#ie#-Leitungen oder Datenboxen miteinander zu vernetzen. Dem heutigen Stand der +Technik entsprechend, werden auf dem Markt eine Reihe von Möglichkeiten ange­ +boten, um PC's zu vernetzen. Diese Netze unterscheiden sich auch dadurch, daß +unterschiedliche Medien zur Datenübertragung benutzt werden. Das #ib#EUMEL- +Datenboxen-Netz#ie# benutzt Telefonkabel, #ib#Ethernet#ie# beispielsweise Koax-Kabel. Auch +Lichtleiter werden zur Datenübertragung benutzt. Entsprechend gibt es eine ganze +Menge Hardware (#ib#Treiber#ie#, Netzzugangsgeräte, Datenboxen, Anschlußkarten), die die +Kopplung zwischen einem #ib#I/O-Kanal#ie# eines Rechners und dem Übertragungsmedium +(Kabel) übernimmt. Das Netz-Hardware-Interface soll als #ib#Schnittstelle#ie# zwischen der +Netz­Software und dem Treiber dienen. Damit wird es möglich, mehrere EUMEL- +Rechner über verschiedene (Teil-) Netze (in dieser Beschreibung Stränge genannt) +und unterschiedliche #ib#Netzhardware#ie# (Treiber) miteinander zu verbinden. Für den +EUMEL-Benutzer soll dabei kein Unterschied in der Benutzung des EUMEL-Netzes +feststellbar sein. +#page# +Neben unterschliedlichen Übertragungsmedien und Treibern gibt es weitere Unter­ +schiede zwischen Netzen: + + - in der Netztopologie (Bus-, Ring- oder Sternnetze), + + - in den Netzzugangsverfahren (Token passing, time slice token, slotting oder + CSMA/CD), + + - in der #ib#Übertragungsgeschwindigkeit#ie#, + + - im Aufbau der einzelnen #ib#Pakete#ie(1,", Aufbau der")# (#ib#Netztelegramm#ie#e). + +Alles, was mit den ersten drei Punkten zusammenhängt, wird von den Netzzugangs­ +geräten behandelt. + +Der Paketaufbau aber muß zumeist im Rechner geschehen und kann in den seltens­ +ten Fällen ganz vom Treiber übernommen werden. Ebenso kann der Treiber aus den +empfangenen Paketen nicht immer die Teile herausfiltern, die von der EUMEL- +#ib#Netzsoftware#ie# gebraucht werden. Diese Aufgaben übernimmt das #ib#Netz-Hardware- +Interface#ie#. Das Netz-Hardware-Interface stellt die #ib#Verbindung#ie# zwischen EUMEL- +#ib#Netzsoftware#ie# und den verschiedenen Netzhardwarearten dar. Ähnlich wie bei den +Drucker- und Terminal-Anpassungen wurde ein hardwareabhängiger Teil aus der +Netzsoftware abgetrennt und in einem eigenen #ib#Paket#ie# zusammengefaßt. Beim Start +des Netzes wird durch Angabe des entsprechenden #ib#Netzmodus#ie# für den jeweiligen +#ib#Kanal#ie# die entsprechende Anpassung für den benutzten Treiber ausgewählt. Wenn +andere, neue Treiber angepaßt werden sollen, so müssen lediglich in dem Paket #on("b")##ib#net +hardware interface#ie##off("b")# die entsprechenden Prozeduren hinzugefügt und die #ib#Sprungleisten#ie# +(#ib#SELECT#ie#-Statements) erweitert werden. + +Durch das #ib#Knotenkonzept#ie# in der #ib#Netzsoftware#ie# ist es möglich, über einen #ib#Knoten­ +rechner#ie# Teilnetze (Stränge), die mit unterschiedlicher #ib#Netzhardware#ie# arbeiten, mitein­ +ander zu verbinden. Es sind dann beispielsweise Verbindungen zwischen Rechnern, +die über #ib#Ethernet#ie# vernetzt sind, und Rechnern auf dem EUMEL-Datenboxen-Netz +möglich. Es ist auch möglich, mit einem Rechner Zugang zu einem Netz zu erhalten, +für das spezielle #ib#Netzhardware#ie# erforderlich ist (Datenboxen, Ethernet-Anschluß). Man +kann den Rechner über eine Rechner-Rechner-Kopplung (#ib#V.24#ie#) mit einem Rechner +verbinden, der bereits ans Netz angeschlossen ist, und so (allerdings auf Kosten der +Leistung des #ib#Knotenrechner#ie#s) Netzhardware einsparen. +#page# + +3.2. Arbeitsweise des + Netz-Hardware-Interfaces + + + + + + #goalpage("3.2")# + +Grob vereinfacht kann man sich die Arbeitsweise der #ib#EUMEL-Netz-Software#ie# so vor­ +stellen: + + reset box; + REP + IF zeichen da THEN lies telegramm ein + ELIF telegramm auszugeben THEN gib telegramm aus + FI + PER . + +(Es ist nur der Teil der Software beschrieben, der die Kanalbehandlung betrifft). + + +Das Zusammenspiel zwischen EUMEL-Netz und Netz-Hardware-Interface ge­ +schieht auf folgende Weise: + + + #on("b")#reset box;#off("b")# + REP + IF zeichen da THEN #on("b")#next packet start#off("b")#; + lies telegramm ein + ELIF telegramm auszugeben THEN gib telegramm aus + FI + PER. + + gib telegramm aus: + #on("b")#transmit header#off("b")#; + gib eumelnetztelegramm aus; + #on("b")#transmit trailer #off("b")#. + +Die fett gedruckten Programmteile werden im Netz-Hardware-Interface realisiert, die +anderen Teile stecken in den darüberliegenden Teilen der EUMEL-Netz-Software. +#page# +Beim Senden eines #ib#Telegramm#ie#s wird von der #ib#Netzsoftware#ie# zuerst der #ib#Vorspann#ie# in +einem #ib#Datenraum#ie# an das Hardware-Interface übergeben (#on("b")##ib#transmit header#ie##off("b")#). Im Hard­ +ware-Interface können aus dem Vorspann die entsprechenden Informationen (Tele­ +grammlänge, #ib#Zielstation#ie# usw.) entnommen werden. Dann wird von der Netzsoftware +das Telegramm (inklusive Vorspann) per #on("b")##ib#blockout#ie##off("b")# übergeben. Danach wird #on("b")##ib#transmit +trailer#ie##off("b")# aufgerufen, um dem Hardware-Interface das Ende des Telegramms zu mel­ +den. Beim Empfang ruft die Netzsoftware zuerst die #ib#I/O Control#ie# #ib#Telegrammfreigabe#ie# +auf [7]. Danach wird das erste #ib#Zeichen#ie# des Telegramms angefordert (#on("b")##ib#next packet +start#ie##off("b")#). Falls ein #ib#STX#ie# geliefert wurde, wird das Telegramm per #on("b")##ib#blockin#ie##off("b")# eingelesen. Falls +#ib#Niltext#ie# zurückgeliefert wird, wird von der Netzsoftware #ib#Timeout#ie# angenommen. Alle +anderen Zeichen werden so interpretiert, als ob Störungen aufgetreten wären. Die +Netzsoftware übernimmt die #ib#Fehlerbehandlung#ie#. Dazu wird u. U. ein Leerlesen des +Puffers vom Hardware-Interface verlangt (#on("b")##ib#flush buffers#ie##off("b")#). + +Bei der Einstellung der #ib#Nutzdatenlänge#ie# (#on("b")##ib#data length#ie##off("b")#) ist zu beachten, daß + +a) alle #ib#Station#ie#en, die an einem #ib#Strang#ie# hängen, auf die gleiche Nutzdatenlänge + eingestellt sein müssen. + +b) Wenn mehrere Stränge über #ib#Knoten#ie# miteinander verbunden sind, muß die Nutz­ + länge für Sendungen über Knoten (#on("b")##ib#data length via node#ie##off("b")#) auf allen Stationen des + gesamten Netzes gleich eingestellt sein. Die Zusammenfassung oder Aufteilung + von #ib#Telegramm#ie#en in Knoten ist nicht möglich. + +c) Als mögliche Nutzdatenlänge sind folgende Werte erlaubt: + + 64, 128, 256 und 512 Byte. + + Größere Nutzdatenlängen sind zur Zeit nicht möglich. + +d) Je größer die #ib#Nutzdatenlänge#ie# ist, desto geringer ist der Overhead an #ib#Zeichen#ie#, + die auf den Rechnern verarbeitet werden müssen. Allerdings muß der Rechner + leistungsfähig genug sein, die ankommenden Blöcke schnell genung zu verarbei­ + ten, und die Netztreiber müssen entsprechend große Puffer haben. + + +Alle implementierten Netzanpassungen sollen in einem Netz-Hardware-Interface +zusammengefaßt werden. Dies ist notwendig, um über #ib#Knotenrechner#ie# Netzstränge +verbinden zu können, die mit unterschiedlicher #ib#Netzhardware#ie# arbeiten. So können +zum Beispiel ein #ib#Strang#ie#, der mit Datenboxen aufgebaut ist, und ein #ib#Ethernet#ie#-#ib#Strang#ie# +über einen Knotenrechner miteinander verkoppelt werden. +#page# +Aus diesem Grund wurden #on("b")#Netzmodi#off("b")# eingeführt. Man kann dadurch, daß die Netz­ +modi, genau wie die #ib#Kanal#ie#angaben, in der #ib#Datei#ie# #on("b")##ib#netz#ie##off("b")# niedergelegt sind, ohne Aus­ +tausch einer Softwarekomponente die Netzhardware wechseln. Es gibt auch die +Möglichkeit, durch verschiedene Netzmodi unterschiedliche Treiber an ein und das­ +selbe Netz anzuschließen. Beispielsweise gibt es für einige Rechnertypen Steckkarten, +mit denen der Rechner an das Ethernet angeschlossen werden kann. Man kann, +wenn diese Karten angepaßt sind, den #ib#Ethernet#ie#-Zugang über verschiedene Netz­ +anschlußkarten realisieren. + +Das Netz-Hardware-Interface muß folgende Aufgaben übernehmen: + + Bei der Ausgabe an den Treiber: + + - Generieren und Ausgeben des #ib#Paket#ie#headers, + - Umsetzen von logischen Stationsadressen (#ib#Stationsnummer#ie#n) in phy­ + sische #ib#Adresse#ie#n, + - Ausgeben der Daten (EUMEL-Netz-#ib#Telegramm#ie#e), + - Generieren und Ausgeben des Trailers und evtl. Auffüllen des Pakets mit + #ib#Füllzeichen#ie#, falls auf dem Netz eine Mindestlänge für Pakete gefordert + wird. + + Bei der Eingabe vom Treiber: + + - Weglesen von #ib#Füllzeichen#ie#, + - Prüfen der #ib#Adresse#ie#n, + - Weglesen von #ib#Paket#ie#teilen, die in der EUMEL-Netz-Software nicht + gebraucht werden. + + Weiterhin können Funktionen wie + + - Reset des Treibers, + - Prüfung, ob Stationsadresse und #ib#Adresse#ie# im Treiber übereinstimmen, + - Statistik und Service + + durch das Netz-Hardware-Interface übernommen werden. + +Dazu wird ein Satz von Prozeduren über die #ib#DEFINES#ie#-#ib#Schnittstelle#ie# des Netz- +Hardware-Interfaces zur Verfügung gestellt. Wenn neue Treiber oder Netzarten +implementiert werden sollen, so muß an diesem Interface nichts geändert werden. Die +herausgereichten Prozeduren realisieren #ib#Sprungleisten#ie# (#ib#SELECT#ie#-Statements), über +die durch Erweiterung (#ib#CASE#ie#) die Prozeduren erreicht werden können, die den ent­ +sprechenden #ib#Netzmodus#ie# realisieren. Außerdem werden Informationsprozeduren für die +darüberliegenden Programmteile zur Verfügung gestellt. +#page# + +3.3. Netztreiber + + #goalpage("3.3")# +Unter #ib#Netztreiber#ie#n versteht man die Einheiten, die den Anschluß des Rechners an ein +Netz realisieren. Das können #ib#Netzbox#ie#en sein, die mit dem Rechner über eine #ib#V.24#ie#- +Leitung verbunden sind, aber auch Anschlußkarten, die direkt auf den Datenbus des +Rechners gehen. Falls die #ib#Schnittstelle#ie# der Treiber-Hardware eine andere als die +serielle #ib#V.24#ie# ist, muß in der Regel eine Anpassung für die Hardware im #ib#SHard#ie# vorge­ +nommen werden. + +Falls der Treiber über eine serielle #ib#V.24#ie#-#ib#Schnittstelle#ie# mit dem Rechner verbunden +ist, wie das auch bei der direkten Kopplung oder dem Datenboxennetz der Fall ist, +wird die hohe #ib#Übertragungsgeschwindigkeit#ie# auf dem eigentlichen Netz durch die +relativ geringe Übertragungsgeschwindigkeit auf der #ib#V.24#ie#-#ib#Schnittstelle#ie# zwischen +Rechner und Treiber (Box) gebremst. Über andere Schnittstellen im Rechner, wenn +sie mit #ib#Stream I/O#ie# [7] betrieben werden, kann man dies vermeiden. Diese Schnitt­ +stellen müssen vom SHard bedient werden. + +Wenn in den Rechner integrierte Netztreiber (Netzanschlußkarten) benutzt werden +sollen, so muß in der Regel die Behandlung dieser Netzanschlußkarte im SHard +durchgeführt werden. + +Um effizient implementieren zu können, sollte darauf geachtet werden, daß möglichst +wenig zusätzliche #ib#Zeichen#ie# von der #ib#Netzsoftware#ie# bzw. dem Netz-Hardware-Inter­ +face bearbeitet werden müssen. Das Auffüllen von Paketen auf eine Mindestlänge +sollte möglichst vom Treiber gemacht werden, ebenso wie das Weglesen dieser +Zeichen. + +Um einen sicheren und effektiven Netzbetrieb zu garantieren, sollten die Treiber +folgende Eigenschaften haben: + + - Die #ib#Stationsadresse#ie# ist im Treiber festgelegt, sie soll nicht ohne weiteres + verändert werden können (Datenschutz). + - Der Treiber reicht nur #ib#Paket#ie#e mit richtiger #ib#Zieladresse#ie#, keine #ib#Broad- oder + Multicasts#ie# an die Netzsoftware weiter. + - Der Treiber sendet nur #ib#Paket#ie#e mit richtiger #ib#Absenderadresse#ie# bzw. setzt die + Absenderadresse selbst ein. + - Die am Treiber eingestellte #ib#Adresse#ie# kann abgefragt werden, oder es wird, + wenn ein Paket mit falscher #ib#Absenderadresse#ie# vom Rechner kommt, eine + #ib#Fehlermeldung#ie# an den Rechner gegeben. Die Fehlermeldung muß durch das + Netz-Hardware-Interface in den #on("b")##ib#report#ie##off("b")# eingetragen werden. + - Falls Pakete mit #ib#Füllzeichen#ie# aufgefüllt werden müssen, sollten die Füll­ + zeichen durch den Treiber generiert und beim Empfang wieder entfernt + werden. + - Falls mehrere Betriebsmodi möglich sind, so sollten sie softwaremäßig + einstellbar sein. + - Falls die Treiber über eine serielle #ib#Schnittstelle#ie# an den Rechner angeschlos­ + sen werden, so sollte der Treiber konfigurierbar sein. In jedem Fall sollte die + serielle Schnittstelle mit #ib#Flußkontrolle#ie# (#ib#RTS/CTS#ie#) implementiert werden. + +Zusätzlich ist ein Transparent-Modus als #ib#Netzmodus#ie# von Vorteil: + + - Der Modus (transparent) kann zu Testzwecken benutzt werden. Beispiels­ + weise um auch mit Rechnern kommunizieren zu können, die über Netz + erreichbar sind, aber kein EUMEL-Netz-#ib#Protokoll#ie# benutzen. + + Modus n: transparent. + + Ausgabeseitig: Das #ib#Paket#ie# wird unverändert ausgegeben. + #ib#Adresse#ie#n usw. müssen schon im Paket vor­ + handen sein. Es wird nicht mit #ib#Füllzeichen#ie# + aufgefüllt. + Eingabeseitig: Das Paket wird unverändert an die Netzsoft­ + ware weitergegeben. + +#page# + +3.4. Prozedurschnittstelle + des EUMEL-Netzes + + + + + + #goalpage("3.4")# +Im PACKET #on("b")##ib#net hardware interface#ie##off("b")# sind folgende Prozeduren untergebracht: + + + + BOOL PROC #ib#blockin#ie# + (DATASPACE VAR ds, INT CONST seite, abstand, länge): + + Versucht, #on("b")#länge#off("b")# Zeichen vom #ib#Kanal#ie# einzulesen. Liefert TRUE, wenn alle + Zeichen eingelesen wurden, FALSE, wenn innerhalb einer bestimmten + Zeit nicht alle #on("b")#länge#off("b")# Zeichen eingelesen werden konnten (z.B. weil der + Kanal nicht mehr Zeichen anliefert). Die eingelesenen Zeichen werden im + #ib#Datenraum#ie# #on("b")#ds#off("b")# in #ib#Seite#ie# #on("b")#seite#off("b")# ab #on("b")#abstand#off("b")# bis #on("b")#abstand#off("b")# + #on("b")#länge#off("b")# - 1 abge­ + legt. + + #ib#Fehlerfall#ie#: + + #on("b")#blockin Abbruch#off("b")# + + Es werden weniger #ib#Zeichen#ie# innerhalb einer festgelegten Zeitspanne über + den Kanal angeliefert, als mit #on("b")#länge#off("b")# gefordert. + + Passiert z.B., wenn die Kabel während einer Netzübertragung unter­ + brochen werden, oder wenn die Gegenstelle abgeschaltet wird. Das + #ib#Telegramm#ie# wird vernichtet, die Prozedur liefert FALSE, es wird eine + entsprechende Meldung im #on("b")##ib#report#ie##off("b")# erzeugt. + + PROC #ib#blockout#ie# + (DATASPACE CONST ds, INT CONST seite, abstand, länge): + + Der Inhalt von Seite #on("b")#seite#off("b")# des #ib#Datenraum#ie#s #on("b")#ds#off("b")# wird von #on("b")#abstand#off("b")# bis + #on("b")#abstand#off("b")# + #on("b")#länge#off("b")# - 1 ausgegeben. +#page# + PROC #ib#set net mode#ie# (INT CONST mode): + + Es wird der #ib#Netzmodus#ie# #on("b")#mode#off("b")# eingestellt. Im Netz-Hardware-Interface + müssen alle Initialisierungen und Einstellungen vorgenommen werden, + damit die mit #on("b")#mode#off("b")# geforderte #ib#Netzhardware#ie# unterstützt wird. Diese + Prozedur wird bei jedem #on("b")##ib#start#ie##off("b")#-Kommando in der Netztask aufgerufen. + Kann als Initialisierungsprozedur für dieses PACKET verwendet werden. + Übergibt den in der #ib#Datei#ie# #on("b")##ib#netz#ie##off("b")# für diesen #ib#Kanal#ie# verlangten Netzmodus an + das Netz-Hardware-Interface. Nach Aufruf dieser Prozedur müssen die + wertliefernden Prozeduren #on("b")##ib#net mode#ie#, #ib#mode text#ie#, #ib#data length#ie##off("b")# und #on("b")##ib#data + length via node#ie##off("b")# korrekt initialisiert sein. Der Aufruf von #on("b")##ib#net addess#ie##off("b")# muß + die korrekten (physikalischen) #ib#Adresse#ie# der #ib#Station#ie#en liefern. + + TEXT PROC net address (INT CONST stationsnummer): + + Liefert die (Hardware-) Netz-#ib#Adresse#ie#, über die der EUMEL-Rechner + mit der Stationsnummer #on("b")##ib#stationsnummer#ie##off("b")# beim aktuell für diesen Kanal + eingestellten #ib#Netzmodus#ie# erreichbar ist. Auf diese #ib#Adresse#ie# muß der Treiber + des entsprechenden Rechners eingestellt sein. Auch die eigene Netz- + Adresse muß mit der im Treiber eingestellten #ib#Adresse#ie# übereinstimmen. + Insbesondere müssen alle Stationen, die auf dem Netz arbeiten, dieselbe + Netz-Adresse für eine #ib#Stationsnummer#ie# errechnen. + + TEXT PROC #ib#mode text#ie#: + + Liefert den Text (Namen) des eingestellten #ib#Netzmodus#ie#. Wird in #on("b")##ib#net + manager#ie##off("b")# benutzt, um den Netzmodus im #on("b")##ib#report#ie##off("b")# anzugeben. + + TEXT PROC mode text (INT CONST mode): + + Liefert den Text (Namen) zu dem #ib#Netzmodus#ie# #on("b")#mode#off("b")#. + + INT PROC #ib#data length#ie# (INT CONST mode): + + Liefert die #ib#Nutzdatenlänge#ie# (#ib#Länge#ie# der Nettodaten des Eumel- + Telegramms) im Netz. Wird von #on("b")##ib#basic net#ie##off("b")# beim Neustart aufgerufen. Muß + in einem Netz auf allen Stationen eines #ib#Strang#ie#s denselben Wert liefern. + + Erlaubte Werte: 64, 128, 256 und 512. +#page# + INT CONST #ib#data length via node#ie#: + + Liefert die #ib#Nutzdatenlänge#ie# für Sendungen, die über #ib#Knoten#ie# gehen. + Muß auf allen Stationen des Netzes gleich sein. + + Erlaubte Werte: 64, 128, 256 und 512. + + PROC #ib#decode packet length#ie# (INT VAR value): + + Die #ib#Länge#ie# eines Netztelegramms ist im #ib#Telegramm#ie# codiert enthalten. Mit + dieser Prozedur wird aus dem Telegrammkopf die Telegrammlänge ermit­ + telt: + + Falls beim Aufruf dieser Prozedur in #on("b")#value#off("b")# der Wert des Feldes #on("b")#head#off("b")# aus + der Struktur #on("b")#vorspann#off("b")#, die in #on("b")#ds#off("b")# per #on("b")##ib#transmit header#ie##off("b")# übergeben wurde, + enthalten ist, so wird in #on("b")#value#off("b")# die Länge des EUMEL-Netztelegramms + zurückgeliefert. + + PROC #ib#flush buffers#ie#: + + Liest den Eingabepuffer des #ib#Netzkanal#ie#s leer. Die eingelesenen Zeichen + werden vernichtet. Wird nach Erkennen von #ib#Übertragungsfehler#ie#n aufge­ + rufen. + + TEXT PROC #ib#next packet start#ie#: + + Liefert genau ein #ib#Zeichen#ie# (in der Regel das erste Zeichen des EUMEL- + Netztelegramms). Wird von der Netzsoftware immer dann aufgerufen, + wenn ein neues #ib#Paket#ie# erwartet wird. + + Bedeutung des gelieferten Zeichens für die #ib#Netzsoftware#ie#: + + #ib#STX#ie#: korrekter #ib#Telegrammanfang#ie# (ist das erste Zeichen des + EUMEL-Netztelegramms). Der Rest des EUMEL-Netztele­ + gramms steht im Eingabepuffer, ist also über #ib#blockin#ie# lesbar. + Vorher wurden nur Zeichen eingelesen, die zum verwendeten + #ib#Netzprotokoll#ie# gehören (z.B. #ib#Ethernet#ie#-#ib#Adresse#ie#n, #ib#Füllzeichen#ie# + usw.). + niltext: kein neues Telegramm da + + jedes andere Zeichen: + Fehler. Entweder wurden Störzeichen eingelesen oder es + gingen Zeichen verloren. #ib#Fehlerbehandlung#ie# erfolgt durch die + Netzsoftware. +#page# + PROC #ib#transmit header#ie# (DATASPACE CONST ds): + + Wird vor Ausgabe eines jeden #ib#Telegramm#ie#s aufgerufen. In dem #ib#Datenraum#ie# + #on("b")#ds#off("b")# wird von der EUMEL-Netz-Software der #on("b")##ib#Vorspann#ie##off("b")# übergeben. Über + den jeweiligs eingestellten #ib#Netzmodus#ie# kann für jede implementierte Netz­ + art über eine #ib#Sprungleiste#ie# (#ib#SELECT#ie#) die Prozedur angesprungen werden, + die den #ib#Header#ie# für den eingestellten Netzmodus erstellt und ausgibt. + Struktur des von der EUMEL-Netz-Software benutzten Headers: + + BOUND STRUCT + (INT head, + zwischenziel, + zielrechner, + quellrechner, + strom, + sequenz, + seitennummer ) VAR vorspann. + + Aus dem Inhalt des Feldes #on("b")#head#off("b")# kann mittels #on("b")##ib#decode packet length#ie##off("b")# die + Gesamtlänge des EUMEL-Netztelegramms errechnet werden. + + PROC #ib#transmit trailer#ie#: + + Wird nach Ausgabe eines jeden Telegramms aufgerufen. Evtl. notwendige + Nachspänne können ausgegeben werden. Die notwenigen Informationen + wurden in #on("b")##ib#transmit header#ie##off("b")# übergeben und müssen aufbewahrt werden, + falls sie im Trailer mitgeliefert werden müssen. Kann auch dazu benutzt + werden, den unter diesem Packet liegenden Schichten (#ib#SHard#ie# oder Hard­ + ware) das Ende des Telegramms mitzuteilen. Notwendige #ib#Füllzeichen#ie# + können in dieser Prozedur in das #ib#Paket#ie# eingebaut werden. + + PROC #ib#reset box#ie# (INT CONST net mode): + + Kann zur Initialisierung der #ib#Netzhardware#ie# benutzt werden. Wird von #on("b")##ib#basic + net#ie##off("b")# beim jedem Neustart aufgerufen. + + INT PROC #ib#max mode#ie#: + + Liefert den Wert des größten erlaubten (implementierten) #ib#Netzmodus#ie#. + + INT PROC #ib#net mode#ie#: + + Liefert den eingestellten Netzmodus. +#page# +#pagenr ("%", 45)##setcount (1)##block##pageblock##count per page# +#headeven# +#center#EUMEL Netzbeschreibung +#center#____________________________________________________________ + +#end# +#headodd# +#center#Anhang +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +Netz - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#Netz - % +#end# +#clear pos##lpos(1.0)##rpos(9.5)##goalpage("A")# + +Anhang: Netz-Meldungen#goalpage("A.1")# + +Mit dem Kommando #on("b")##ib#list#ie# (/"net list")#off("b")# (siehe Teil 1) erhalten Sie eine temporäre #ib#Datei#ie# +auf den Bildschirm. Diese Datei könnte ungefähr so aussehen: + +____________________________________________________________________________ + + N e u e r S t a r t 12:44 Stationsnummer : 38 + 01.06.87 12:55 net port 8:20:Nicht zustellbar. . Empfänger: "net dok". Quelle 34 Taskindex: 255 + 02.06.87 06:30 net port 8:1:wdh data. sqnr 7. Absender: "net dok". Ziel 34 Taskindex: 255 + 02.06.87 07:03 net port:20:Sequenzfehler: soll 13 ist 14. Empfänger: "POST". Quelle 33 Taskindex: + 02.06.87 07:03 net port:blockin abbruch + 02.06.87 07:03 net port:20:Sequenzreset von 13 auf 10. Empfänger: "POST". Quelle 33 Taskindex: 29 + 02.06.87 07:36 net port:Call gelöscht."net dok". Strom 1 + 02.06.87 07:43 net port 8:verbotene Route: 34 + 02.06.87 07:50 net port:Header inkorret eingelesen: %0 %2 + 02.06.87 07:50 net port:buffers flushed + 02.06.87 07:52 net port:Weiterleitung nicht möglich für 34 + 02.06.87 07:53 net port 8:skipped0 6 G O 1 0 . 0 %13 %10 2 8 0 6 0 6 G O 1 0 . 0 %13 %10 2 8 0 + 02.06.87 08:14 net port 8:skipped%13 %10 S p e c . R e c e i v e E r r o r C 2 + 02.06.87 08:21 net port:20:Reopen. Empfänger: "WÜFE". Quelle 40 Taskindex: 22 + 02.06.87 09:25 net port:1:etwas rueckgespult. Absender: "-". Ziel 33 Taskindex: 51 + 02.06.87 09:25 net port:1:wdh data. sqnr 20. Absender: "-". Ziel 33 Taskindex: 51 + 02.06.87 09:54 net port:20:Blocknummer falsch, neu: 192, alt : -1. Empfänger: "WÜFE". Quelle 44 + 02.06.87 10:12 net port:Daten ohne Eroeffnung von 40 Sequenznr 7 + 02.06.87 10:23 net port:Header inkorret eingelesen: O X 0 3 8 B O X 0 4 4 E U %2 + 02.06.87 10:23 net port:buffers flushed + 02.06.87 10:49 net port:1:wdh open. Absender: "-". Ziel 33 Taskindex: 255 + 02.06.87 10:49 net port:2:wdh open. Absender: "net dok". Ziel 33 Taskindex: 255 + 02.06.87 10:53 net port:1:Sequenzfehler: soll 2 ist 3. Empfänger: "net dok". Quelle 33 Taskindex: + 02.06.87 10:54 net port:1:Sequenzreset von 8 auf 5. Empfänger: "net dok". Quelle 33 Taskindex: 11 + 02.06.87 10:56 net port:2:etwas rueckgespult. Absender: "-". Ziel 33 Taskindex: 51 + bekannte Stationen: + 1(8,1) 2(8,2) 3(8,3) 4(8,4) 5(8,5) 6(8,6) 7(8,7) 8(8,8) 9(8,9) 10(8,10) + 11(8,11) 12(8,12) 13(8,13) 14(8,14) 15(8,15) 16(8,16) 17(8,17) 18(8,18) + 19(8,19) 20(8,20) 21(8,21) 22(8,22) 23(8,23) 24(8,24) 25(8,25) 26(8,26) + 27(8,27) 28(8,28) 29(8,29) 30(8,30) 31(8,31) 32(8,32) 33(9,33) 34(8,34) + 35(9,35) 36(9,36) 37(9,37) 39(9,39) 40(9,40) 41(9,41) 42(9,42) 43(9,43) + 44(9,44) 45(9,45) 46(9,46) 47(9,47) 48(9,48) + -------- + Eingestellte Netzmodi: + net port 8 haengt an Kanal 8, Modus: (1) EUMEL-Netz 64 Byte + net port haengt an Kanal 9, MODUS: (11) ETHERNET via V.24 512 Byte + + Nutzdatenlänge 512 Byte + Nutzdatenlänge bei indirekter Verbindung: 64 Byte + ******** + Netz-Software vom 23.05.87 + Rechner 38 um 11:11 + net port 8 + + Strom 1 (sqnr7/8) sendet an 34 . Absender ist "net dok". + net port + + Strom 1 (sqnr45/45) empfaengt von 40 . Empfaenger ist "PUBLIC". + +____________________________________________________________________________ +#page# +Die Datei enthält den aktuellen #on("b")##ib#report#ie##off("b")#, in dem #ib#Fehlermeldung#ie#en der einzelnen Tasks +gesammelt werden. Außerdem wird der Zustand aller Verbindungen (Ströme) von allen +#on("b")##ib#net port#ie##off("b")#'s angezeigt. Im #on("b")#report#off("b")#-Teil kann man drei Informationsblöcke unterscheiden: + +a) den Block mit den Fehlermeldungen. Es werden jeweils Datum, Uhrzeit, der Name + des betroffenen #on("b")#net port#off("b")# und, wenn notwendig, die #ib#Stromnummer#ie# angegeben. + Darauf folgt der Meldungstext, der auch Informationen über Absender und Emp­ + fänger enthalten kann. + + : [<#ib#Stromnummer#ie#> : ] + + +b) den Block mit der Liste der bekannten #ib#Station#ie#en. Ein Eintrag in dieser Liste ent­ + hält jeweils die Stationsnummer der bekannten Station und in Klammern dahin­ + ter die Nummer des Kanals auf diesem Rechner, über den die Station erreichbar + ist und die Nummer der nächsten #ib#Zwischenstation#ie#. + + (,) + + Bei direkt erreichbaren Stationen ist Zwischenstation gleich #ib#Zielstation#ie#. + + Hinweis: Auch #ib#gesperrt#ie#e Stationen erscheinen in dieser Liste. + + +c) den Block, der Auskunft über die Netzinstallation gibt. Es werden für jeden Netz­ + kanal die eingestellten Netzmodi angegeben. Des weiteren werden die beiden + Größen #on("b")##ib#data length#ie##off("b")# (#ib#Nutzdatenlänge#ie#) und #on("b")##ib#data length via node#ie##off("b")# (Nutzdatenlänge bei + indirekter Verbindung) angegeben. Zusätzlich erscheinen noch die #ib#Netzversion#ie# und + die genaue Uhrzeit, zu der dieser #on("b")#report#off("b")# erstellt wurde. + +#page# +Für jeden #on("b")##ib#net port#ie##off("b")# wird pro aktivem #ib#Strom#ie# folgende Meldung generiert: + +Strom (sqnr/) + + + #ib#Stromnummer#ie# + + #ib#Sequenznummer#ie# des gerade bearbeiteten #ib#Telegramm#ie#s + + Bei #ib#Sendeströme#ie#n die Nummer der letzten zu übertragenden + #ib#Sequenz#ie#, bei Empfangsströmen in der Regel die Nummer der + letzten Sequenz der gerade übertragenen #ib#Datenraumseite#ie#. + +<#ib#Zustand#ie#> Hier wird die Aktion (senden, empfangen usw.) und die Partner­ + station angegeben. + +<#ib#Partner#ie#> Der Name der Task mit der kommuniziert wird. + + +Die Meldungen, die in der #ib#Datei#ie# #on("b")##ib#report#ie##off("b")# protokolliert werden, kann man in verschiedene +Gruppen einordnen. Die eine Gruppe beschreibt Störungen durch #ib#Zeichenverluste#ie# +oder ­verfälschungen, eine andere Gruppe protokolliert besondere Situationen, bei­ +spielsweise den Abbruch von #ib#Übertragung#ie#en, und die letzte Gruppe befasst sich mit +#ib#Fehlermeldung#ie#en, die ein Eingreifen von aussen notwendig machen. Je nachdem, ob +die Station, auf der die Meldung protokolliert wird, Empfänger oder Absender ist, wird +bei den Meldungen #ib#Stationsnummer#ie# und Taskname des Kommunikationspartners mit +angegeben. + +Zur ersten Gruppe gehören: + +#ib(4)##ib#skipped#ie##ie(4)# + 'skipped' oder skipped mit einem Zusatztext erscheint, wenn Zei­ + chen eingelesen wurden, die zu keinem gültigen #ib#Telegramm#ie# ge­ + hören. Dies kann passieren, wenn auf der Leitung zwischen + Rechner und Box #ib#Zeichen#ie# verlorengegangen sind. Auch nach dem + Einschalten oder nach einem Reset auf Box oder Rechner kann + diese Meldung kommen. Mindestens ein Teil der eingelesenen + Daten wird mit ausgegeben, wobei Steuerzeichen durch % und den + Code des Steuerzeichens dargestellt werden. Die einzelnen Zeichen + werden durch ein Blank voneinander getrennt. +#page# +#ib(4)##ib#Sequenzfehler#ie##ie(4)# + Die #ib#Sequenznummer#ie# ist zu groß, es fehlen also Telegramme. Die + Gegenstation wird aufgefordert, ab einem früheren Telegramm zu + wiederholen. + +#ib(4)#wdh data#ie(4)# + Das letzte Telegramm wird erneut geschickt. Passiert, wenn die + #ib#Quittung#ie# für dieses Telegramm nach einer bestimmten Zeit nicht + angekommen ist. + +#ib(4)##ib#Sequenzreset#ie##ie(4)# + Die #ib#Sequenznummer#ie# des empfangenen Telegramms ist kleiner als + die Sequenznummer des vorher empfangenen Telegramms. Die + Verbindung wird bei der zuletzt empfangenen Sequenznummer + fortgesetzt. + +#ib(4)#Blocknummer falsch#ie(4)# + Die #ib#Seitennummer#ie# in dem #ib#Telegramm#ie# ist falsch. + +#ib(4)#etwas rueckgespult#ie(4)# + Auf Anforderung der Gegenseite werden die letzten drei #ib#Datenraum­ + seite#ie#n erneut übertragen. + +#ib(4)#Daten ohne Eroeffnung#ie(4)# + Es werden Telegramme mit einer #ib#Stromnummer#ie# empfangen, zu der + vorher kein OPEN-Telegramm empfangen wurde. In diesem Fall + wird die Gegenstation aufgefordert, die #ib#Übertragung#ie# von vorn zu + beginnen. Diese Meldung kann auch kommen, wenn das Netz neu + gestartet wurde. + +#ib(4)#wdh open#ie(4)# + Die Übertragung wird mit dem #ib#OPEN#ie#-Telegramm von vorn begon­ + nen. Passiert auf Aufforderung durch die Gegenstation oder wenn + das erste OPEN-Telegramm nicht quittiert wurde. + +#ib(4)##ib#buffers flushed#ie##ie(4)# + Alle bereits eingelesenen, aber noch nicht bearbeiteten Zeichen + wurden gelöscht (der #ib#Eingabepuffer#ie# wurde komplett gelöscht). Verur­ + sacht durch schwere Störungen (#ib#Zeichenverluste#ie# oder -verfäl­ + schungen). +#page# +#ib(4)#blockin abbruch#ie(4)# + Es wurden nicht alle Zeichen eines Telegramms innerhalb eines + bestimmten Zeitraums angeliefert. + +#ib(4)#Header inkorrekt eingelesen#ie(4)# + Es wurde ein Fehler in dem Teil des Netztelegramms gefunden, der + nicht zum EUMEL-Netz gehört. + +#ib(4)#Strom falsch in Quittung#ie(4)#: + In der #ib#Quittung#ie# wurde eine nicht zulässige #ib#Stromnummer#ie# festge­ + stellt. Zulässig sind Stromnummern zwischen 1 und 20. + +#ib(4)#Neustart#ie(4)# + Die Gegenstation hat die #ib#Verbindung#ie# von vorne begonnen. + +#ib(4)#Falsche Seitennummer#ie(4)# + Die #ib#Seitennummer#ie# in dem empfangenen Telegramm ist falsch. + Einige Telegramme werden wiederholt. + +#ib(4)#Absteigende Seitennummern#ie(4)# + Die Seitennummer in dem empfangenen Telegramm ist kleiner als + die Seitennummer im vorigen #ib#Telegramm#ie#. Es müssen einige Tele­ + gramme wiederholt werden. + + +Die folgenden Meldungen beschreiben Situationen, die nicht durch #ib#Zeichenverluste#ie# +entstehen, mit denen die #ib#Netzsoftware#ie# selbst fertig wird: + + +#ib(4)#Sendung von Gegenstelle gelöscht#ie(4)# + Die Verbindung wurde von der Gegenstelle abgebrochen. + +#ib(4)#Empfangseintrag freigegeben#ie(4)# + Die Verbindung wurde von der empfangenden #ib#Station#ie# gelöscht, weil + seit dem Eintreffen des letzten Telegramms zuviel Zeit vergangen ist + (#ib#Timeout#ie#). + +#ib(4)#Irrläufer#ie(4)# + Eine #ib#Intertaskkommunikation#ie# innerhalb der eigenen Station wurde + fälschlicherweise über den #on("b")##ib#Collector#ie##off("b")# abgewickelt. Dieser Vorgang + wird abgebrochen. +#page# +#ib(4)#Call-Löschung vorgemerkt#ie(4)# + Sobald der Call abgewickelt ist, wird diese Verbindung gelöscht. + Beispielsweise führt ein vom Benutzer abgebrochenes #on("b")##ib#name#ie##off("b")# zu + dieser Meldung. + +#ib(4)#Call gelöscht#ie(4)# + Die #ib#Verbindung#ie# wurde auf Anforderung durch den Auftraggeber + gelöscht. + +#ib(4)#Quellrechner#ie(4)# + Als #ib#Quellrechnernummer#ie# wurde ein unzulässiger Wert festgestellt. + Zulässig sind Zahlen zwischen 1 und 127. + +#ib(4)#Nicht zustellbar#ie(4)# + Innerhalb eines bestimmten Zeitraums war die #ib#Zieltask#ie# nicht emp­ + fangsbereit. Die Verbindung wird abgebrochen. + +Bei diesen Meldungen sollten die #ib#Routenanweisungen#ie# überprüft werden: + +#ib(4)#Verbotene Route bei Quittung#ie(4)# + Die #ib#Quittung#ie# kommt auf einer nicht erlaubten #ib#Route#ie# an. Dies kann + bei #ib#Vermaschung#ie# passieren, oder aber, wenn eine Station versucht, + sich für eine andere Station auszugeben. + +#ib(4)#Verbotene Route#ie(4)# + Die danach bezeichnete Station versucht, auf einer anderen Route + mit diesem Rechner zu kommunizieren, als auf der Route, die für + diesen Rechner in der Datei #on("b")##ib#netz#ie##off("b")# festgelegt wurde. + + Abhilfe: + #ib#Routentabellen#ie# der beiden (oder, falls die Meldung auf einer + #ib#Knotenstation#ie# erscheint, auf allen beteiligten) Stationen abgleichen. + +#ib(4)#Weiterleitung nicht möglich#ie(4)# + Die #ib#Routeninformationen#ie# auf dem #ib#Knotenrechner#ie#, wo diese Meldung + erscheint, und der sendenden #ib#Station#ie# stimmen nicht überein. Die + angegebene Station ist von dieser Station aus nicht erreichbar. + + Abhilfe: + #ib#Routentabellen#ie# der Stationen überprüfen. + +#ib(4)#Fremdzugriff#ie(4)# + Eine #ib#gesperrt#ie#e Station hat versucht, auf diesen Rechner mit #ib#Sende­ + codes#ie# > 6 zuzugreifen. + + +Folgende Meldungen betreffen '#ib#harte Fehler#ie#'. Diese Fehler werden von der Netzsoft­ +ware nicht abgefangen. In jedem Fall muß das Netz nach einer solchen #ib#Fehler­ +meldung#ie# neu gestartet werden. + +#ib(4)#++++++#ie(4)# + Meldungen dieser Form sind 'harte' Fehler. Der aufgetretene Fehler + wird mit angegeben. Das Netz muß neu gestartet werden, da die + Task, in welcher der Fehler aufgetreten ist, gelöscht wird. + +#ib(4)#Verbindungsengpaß#ie(4)# + Es sind mehr Verbindungen festgestellt worden, als zulässig sind. + Nach dieser Meldung wurde der entsprechende Netport gelöscht. + + +Literaturverzeichnis + + +#goalpage("A.2")# + +#clear pos# +#lpos(1.0)##lpos(2.5)# +#table# +[1] EUMEL-Systemhandbuch, Teil 5, Intertaskkommunikation + GMD St. Augustin, 1986 +[2] EUMEL-Systemhandbuch, Teil 2, Hardware und ihre Steuerung +[3] EUMEL-Systemhandbuch, Teil 8, Spooler +[4] EUMEL-Netz Installationsanweisung + GMD St. Augustin, 1987 +[5] EUMEL-Systemhandbuch, Teil 4, Blockorientierte Ein/Ausgabe +[6] EUMEL-Quellcode, Packet #on("b")#tasks#off("b")# + GMD St. Augustin, 1986 +[7] EUMEL-Portierungshandbuch 8086, Version 8 + GMD St. Augustin, 1987 + +#table end# + + diff --git a/system/net/1.8.7/doc/netzhandbuch.anhang b/system/net/1.8.7/doc/netzhandbuch.anhang new file mode 100644 index 0000000..17d1ece --- /dev/null +++ b/system/net/1.8.7/doc/netzhandbuch.anhang @@ -0,0 +1,58 @@ +#pagenr ("%", 51)##setcount##block##pageblock##count per page# +#headeven# +#center#EUMEL Netzbeschreibung +#center#____________________________________________________________ + +#end# +#headodd# +#center#Anhang +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +Netz - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#Netz - % +#end# +#clear pos##lpos(0.0)##rpos(11.0)##fillchar(".")# +Anhang: Netz-Fehlermeldungen + +#table# +++++++ 50 +Absteigende Seitennummern 48 +blockin abbruch 48 +Blocknummer falsch 47 +buffers flushed 47 +Call gelöscht 49 +Call-Löschung vorgemerkt 49 +Collectortask fehlt 8, 18 +Daten ohne Eroeffnung 47 +Empfangseintrag freigegeben 48 +etwas rueckgespult 47 +Falsche Seitennummer 48 +Fremdzugriff 50 +Header inkorrekt eingelesen 48 +Irrläufer 48 +kein Zugriff auf Station 14 +Neustart 48 +Nicht zustellbar 49 +Quellrechner 49 +Sendung von Gegenstelle gelöscht 48 +Sequenzfehler 47 +Sequenzreset 47 +skipped 46 +Station x antwortet nicht 8, 11, 16 +Station x gibt es nicht 9, 11, 13 +Strom falsch in Quittung 48 +Task "..." gibt es nicht 8 +Verbindungsengpaß 50 +Verbotene Route 49 +Verbotene Route bei Quittung 49 +wdh data 47 +wdh open 47 +Weiterleitung nicht möglich 49 +#table end# + diff --git a/system/net/1.8.7/doc/netzhandbuch.index b/system/net/1.8.7/doc/netzhandbuch.index new file mode 100644 index 0000000..01d8a0f --- /dev/null +++ b/system/net/1.8.7/doc/netzhandbuch.index @@ -0,0 +1,259 @@ +#pagenr ("%", 52)##setcount (1)##block##pageblock##count per page# +#headeven# +#center#EUMEL Netzbeschreibung +#center#____________________________________________________________ + +#end# +#headodd# +#center#Anhang +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +Netz - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#Netz - % +#end# +#clear pos##lpos(0.0)##rpos(11.0)##fillchar(".")# +Anhang: Index + +#table# +/ 8, 9, 24 +Absenderadresse 39 +Absenderstation 28, 32 +Adresse 29, 37, 39, 41, 42 +aktiviere netz 14, 15, 18 +basic net 41, 43 +Baud 6, 18, 25 +blockin 23, 36, 40, 42 +blockout 23, 36, 40 +Broad- oder Multicasts 38 +buffers flushed 47 +CASE 37 +CLOSE 27 +collected destination 22, 24 +Collector 22, 24, 32, 48 +Collectortask 8, 18, 22 +configurate 6 +continue 7, 21 +CRC-Code 26 +DATA 27, 29, 30 +data length 23, 36, 41, 45 +data length via node 23, 36, 41, 42, 45 +Datei 2, 5, 7, 12, 13, 14, 18, 20, 24, 31, 37, 41, 44, 46 +Datenbox 2, 6, 33 +Datenraum 13, 15, 21, 23, 24, 27, 28, 29, 31, 36, 40, 43 +Datenraumseite 23, 46, 47 +decode packet length 42, 43 +define collector 22, 24 +definere netz 15 +DEFINES 37 +define station 5, 22 +definiere netz 14 +Dreher 16 +Durchsatz 3 +Eingabeprozeduren 21 +Eingabepuffer 47 +Empfangspuffer 15 +Empfangsströme 13, 15 +endquelle 28 +endziel 28 +erase 13, 19 +erlaube 14 +Ethernet 33, 34, 36, 37, 42 +EUMEL0 21, 22, 24 +EUMEL-Datenboxen-Netz 33 +EUMEL-Netz-Software 35 +exists 11 +Fehler 8, 16, 17, 18 +Fehlerbehandlung 31, 36, 42 +Fehlerfälle 8 +Fehlerfall 11, 40 +Fehlermeldung 13, 15, 20, 26, 39, 45, 46, 50 +Fehlersituationen 12 +Fehlersuche 16 +Fenstertechnik 31 +fetch 10, 18 +flush buffers 36, 42 +Flußkontrolle 7, 15, 27, 39 +free global manager 10, 19, 31 +Füllzeichen 37, 39, 42, 43 +gesperrt 13, 14, 45, 50 +global manager 19, 31 +harte Fehler 50 +HDLC 31 +Header 43 +Höhere Ebenen 31 +inchar 21 +incharety 23 +Installation 2 +Installationsanleitung 2 +Intertaskkommunikation 48 +I/O Control 36 +I/O-Kanal 33 +Kanal 3, 6, 7, 12, 14, 15, 20, 21, 23, 24, 34, 37, 40, 41 +Kanalnummer 14 +Kanaltask 45 +Knoten 3, 4, 17, 20, 23, 36, 42 +Knotenkonzept 3, 34 +Knotenrechner 34, 36, 49 +Knotenstation 13, 14, 20, 49 +Kommunikation 17 +Kommunikationindirekte 23 +konfigurieren 6 +Länge 29, 41, 42 +Längenangabe 26 +list 10, 12, 17, 44 +listoption 12, 14, 15 +Löschversuche 13 +Manager 10, 19 +Masseschluß 16 +max mode 43 +mode text 41 +Nachbarn 4, 28 +Nachbarstation 24, 28 +name 11, 24, 49 +net 7, 12, 13 +net addess 41 +net hardware interface 34, 40 +net install 7 +net list 12, 15 +net manager 41 +net mode 41, 43 +net port 7, 8, 12, 13, 18, 45, 46 +net timer 14 +netz 7, 14, 15, 20, 37, 41, 49 +Netzbox 3, 6, 20, 33, 38 +Netzdefinition 14 +Netzebene 26 +Netzempfangstask 30 +Netzhardware 2, 17, 21, 24, 33, 34, 36, 41, 43 +Netz-Hardware-Interface 34 +Netzinstallation 17 +Netzkanal 13, 14, 42 +Netzknoten 3 +Netzkonfiguration 7, 20 +Netzmodus 34, 37, 39, 41, 43 +Netzprotokoll 42 +Netzsoftware 2, 3, 18, 20, 34, 36, 38, 42, 48 +Netzstrang 4, 17, 23 +Netztask 15, 16, 21, 24 +Netztelegramm 34 +Netztreiber 38 +Netzübertragungen 12 +Netzversion 2, 45 +next packet start 36, 42 +niltext 11, 36 +Nutzdaten 23 +Nutzdatenlänge 17, 23, 29, 36, 41, 42, 45 +Nutzinformation 29 +nutzlaenge 29 +OPEN 27, 28, 30, 47 +Paket 23, 34, 37, 38, 39, 42, 43 +Pakete, Aufbau der 34 +Partner 46 +Paßwort 19 +Pin-Belegung 6 +port intern 13, 15, 24 +Printerserver 20 +Protokoll 6, 13, 24, 39 +Protokollebenen 25 +Prüfsummen 18 +Quelle 23, 26, 28 +Quellrechnernummer 49 +Quellstationsnummer 20 +quelltask 21, 24, 28 +Querarchivierungen 10 +QUIT 27, 28, 30 +Quittung 30, 31, 47, 48, 49 +Rechnerkopplung 3 +Rendezvouskonzept 21, 31 +report 8, 12, 18, 39, 40, 41, 45, 46 +reserve 10 +RESET 17 +reset box 43 +Route 13, 15, 17, 20, 49 +routen 14 +Routenanweisungen 49 +routen aufbauen 13, 14, 15 +Routeninformationen 20, 49 +Routentabelle 9, 13 +Routentabellen 24, 49 +router 13 +RS422 25 +RTS/CTS 6, 25, 39 +Rückmeldeparameter 21 +run 13 +save 10, 19 +Schnittstelle 3, 15, 18, 20, 25, 33, 37, 38, 39 +SDLC 25, 26 +seite 28, 29, 40 +Seiten 27 +Seitengrenze 23 +Seitennummer 47, 48 +SELECT 34, 37, 43 +send 21, 22, 24, 27, 28, 30, 32 +Sendecode 24 +Sendecodes 50 +Sendeströme 13, 46 +Sendungskonzept 2 +sequenz 28, 29, 46 +Sequenzfehler 47 +Sequenznummer 46, 47 +Sequenzreset 47 +set net mode 41 +SHard 38, 43 +Sicherheitskonzept 19 +Sicherheitsprobleme 19 +skipped 46 +sperre 14 +Spoolmanager 5 +Sprungleiste 43 +Sprungleisten 34, 37 +start 5, 13, 16, 18, 41 +starte kanal 14, 15 +station 2, 5, 8, 10, 12, 13, 16, 19, 20, 22, 24, 26, 31, 32, 36, 41, 45, 48, 49 +Stationen, sicherheitsrelevante 20 +Stationsadresse 38 +Stationsnummer 5, 10, 16, 22, 24, 26, 32, 37, 41, 46 +Stationsnummer maximale 14 +Strang 3, 17, 20, 36, 41 +Stream I/O 23, 38 +strom 28, 30, 46 +Stromnummer 13, 28, 30, 45, 46, 47, 48 +STX 26, 36, 42 +Task-Id 5, 22, 24, 28, 30 +Telegramm 20, 23, 26, 27, 28, 31, 36, 37, 40, 42, 43, 46, 47, 48 +Telegrammanfang 42 +Telegrammformat 26 +Telegrammfreigabe 36 +Textdatei 31 +Timeout 31, 36, 48 +transmit header 36, 42, 43 +transmit trailer 36, 43 +Treiber 33 +Übertragung 26, 30, 46, 47 +Übertragungsfehler 42 +Übertragungsgeschwindigkeit 34, 38 +Übertragungsweg 23 +V24 3, 4, 15, 17, 18, 20, 25, 33, 34, 38 +Verbindung 3, 6, 16, 18, 27, 28, 34, 48, 49 +Vermaschung 4, 49 +Vermittlungsebene 24, 30 +Vorspann 36, 43 +wait 19, 21, 24, 27, 32 +Worker 5 +Zeichen 36, 38, 40, 42, 46 +Zeichenverluste 46, 47, 48 +Zeitüberwachung 26, 29 +ziel 28 +Zieladresse 38 +Zielstation 4, 8, 24, 28, 30, 36, 45 +Zieltask 21, 22, 24, 28, 32, 49 +Zustand 46 +Zwischenstation 45 +#table end# + diff --git a/system/net/1.8.7/source-disk b/system/net/1.8.7/source-disk new file mode 100644 index 0000000..5a39f6c --- /dev/null +++ b/system/net/1.8.7/source-disk @@ -0,0 +1 @@ +grundpaket/11_austausch.img diff --git a/system/net/1.8.7/src/basic net b/system/net/1.8.7/src/basic net new file mode 100644 index 0000000..c5e9278 --- /dev/null +++ b/system/net/1.8.7/src/basic net @@ -0,0 +1,1148 @@ +PACKET basic net DEFINES (* D. Heinrichs *) + (* Version 10 (!) *) (* 18.02.87 *) + nam, (* 03.06.87 *) + max verbindungsnummer, (* *) + neuer start, + neue routen, + packet eingang, + neue sendung, + zeitueberwachung, + verbindung, + loesche verbindung: + +TEXT PROC nam (TASK CONST t): + IF t = collector THEN name (t) + ELIF station (t) <> station (myself) + THEN "** fremd "+text(station(t))+" **" + ELSE name (t) + FI +END PROC nam; + +INT PROC tasknr (TASK CONST t): + IF t = collector THEN maxtasks + ELSE index (t) + FI +END PROC tasknr; + +LET + maxtasks = 127, + maxstat = 127, + max strom = 20, + max strom 1 = 21, + stx = ""2"", + code stx = 2, + error nak = 2, + seiten groesse = 512, + dr verwaltungslaenge = 8, + dr verwaltungslaenge2=10, + openlaenge = 24, + vorspannlaenge = 14, + ack laenge = 12, + min data length = 64, + (* Codes der Verbindungsebene *) + + task id code = 6, + name code = 7, + task info code = 8, + routen liefern code = 9, + + (* Typen von Kommunikationsströmen *) + + send wait = 0, + zustellung = 1, + call pingpong = 2, + call im wait = 3, + call im abbruch = 4, + call in zustellung = 5, + + (*quittungscodes*) + + ok = 0, + von vorne = 1, + wiederhole = 2, + loesche = 3, + beende = 4; + +LET STEUER = + STRUCT ( + INT head, + zwischenziel, + zielrechner, + quellrechner, + strom, + sequenz, + seitennummer, + TASK quelle,ziel, + INT sende code); + +BOUND STEUER VAR open block; + +BOUND STRUCT (STEUER steuer, INT typ, maxseq) VAR info block; + +BOUND STRUCT ( + INT head, + zwischenziel, + zielrechner, + quellrechner, + strom, + sequenz, + seitennummer) VAR vorspann ; + +LET ACK = STRUCT ( + INT head, + zwischenziel, + zielrechner, + quellrechner, + strom, + code); +BOUND ACK VAR ack packet ; +BOUND ACK VAR transmitted ack packet; + +BOUND STRUCT (ROW maxstat INT port, + ROW maxstat INT zwischen) VAR route; + +INT CONST max verbindungsnummer := max strom; +INT VAR codet,net mode, nutzlaenge := data length, + data len via node := data length via node; + +TEXT VAR buffer first; + +DATASPACE VAR work space := nilspace; +DATASPACE VAR transmitted ack space := nilspace; + + +INT VAR pakete pro seite, + pakete pro seite minus 1, + packets per page via node, + packets per page via node minus 1, + datenpacketlaenge via node, + datenpacketlaenge ; + +INT VAR strom; +INT VAR last data := -1; +INT VAR own:=station (myself) , + quit max := 3, + quit zaehler := 3, + own256 := 256*own; +INT CONST stx open := code stx+256*openlaenge, + stx quit := code stx+256*acklaenge; + + STEUER VAR opti; + ROW maxstrom1 STEUER VAR verbindungen; + ROW maxstrom1 DATASPACE VAR netz dr; + ROW maxstrom1 INT VAR zeit, typ, open try; + FOR strom FROM 1 UPTO maxstrom1 REP vdr := nilspace; forget (vdr) PER; + ROW maxstrom INT VAR dr page ; + ROW maxtasks INT VAR alter call; + +.vx : verbindungen (strom). + +vdr: netz dr (strom). + + via node: + vx.zielrechner <= 0 OR vx.quellrechner <= 0 OR + transmit via node OR receive via node. + + transmit via node: + route.zwischen (vx.zielrechner) <> vx.zielrechner AND vx.zielrechner <> own. + + receive via node: + route.zwischen (vx.quellrechner) <> vx.quellrechner AND vx.quellrechner <> own. + +falsche stromnummer: strom < 1 OR strom > maxstrom. + +zielrechner ok: vorspann.zielrechner > 0 AND vorspann.zielrechner <= maxstat. + +quellrechner ok: vorspann.quellrechner > 0 + AND vorspann.quellrechner <= maxstat. + +call aufruf: typ(strom) >= call pingpong. + +alles raus: vx.seitennummer = -1 AND letztes packet der seite . + +letztes packet der seite : +(vx.sequenz AND packets per page minus 1) = packets per page minus 1. + +neue verbindung: code t = open laenge. + +PROC neue routen: + route := old ("port intern"); +END PROC neue routen; + +PROC neuer start (INT CONST empfangsstroeme, mode): + net mode := mode; + strom := 1; + neue routen; + transmitted ack space := nilspace; + workspace := nilspace; + open block := workspace; + info block := workspace; + nutzlaenge := data length; + data len via node := data length via node; + pakete pro seite:= seitengroesse DIV nutzlaenge; + pakete pro seite minus 1 := pakete pro seite -1; + packets per page via node := seitengroesse DIV data len via node; + packets per page via node minus 1 := packets per page via node - 1; + datenpacketlaenge := vorspannlaenge + nutzlaenge; + datenpacketlaenge via node := vorspannlaenge + data len via node; + vorspann := workspace; + ack packet := workspace; + transmitted ack packet := transmitted ack space; + FOR strom FROM 1 UPTO maxstrom1 REP + vx.strom := 0; forget (vdr) + PER; + INT VAR i; + FOR i FROM 1 UPTO maxtasks REP alter call (i) := 0 PER; + quitmax := empfangsstroeme; + own:=station (myself); + quit zaehler := quit max; + own256 := 256*own; + reset box (net mode); + buffer first := ""; + flush buffers; + INT VAR err; + fehlermeldung ruecksetzen. + + fehlermeldung ruecksetzen: + control (12,0,0,err). + +END PROC neuer start; + +DATASPACE PROC verbindung (INT CONST nr): + INT VAR memory := strom; + strom := nr; + infoblock.steuer := verbindungen (nr); + infoblock.typ := typ (nr); + infoblock.maxseq := dspages (netzdr(nr)) * packets per page; + strom := memory; + workspace +END PROC verbindung; + +PROC neue sendung (TASK CONST q,z, INT CONST cod,z stat, DATASPACE CONST dr): + + naechste verbindung vorbereiten; + forget (vdr); vdr := dr; + sendung starten (q, z, z stat, cod) +END PROC neue sendung; + +PROC zeitueberwachung + (INT VAR snr, TASK VAR q, z, INT VAR ant,DATASPACE VAR dr): + snr INCR 1; + FOR strom FROM snr UPTO maxstrom REP zeitkontrolle PER; + snr := 0. + +zeitkontrolle: + IF vx.strom <> 0 AND zeit(strom) > 0 + THEN + zeit(strom) DECR 1; + IF sendung noch nicht zugestellt + THEN + IF zeit(strom) = 0 + THEN + empfangsreport ("Nicht zustellbar. "); + loesche verbindung (strom) + ELSE + snr := strom; + q := vx.quelle; + z := vx.ziel; + ant := vx.sendecode; + dr := vdr; + LEAVE zeitueberwachung + FI + ELIF zeit(strom) = 0 + THEN wiederholen + FI + FI. + +sendung noch nicht zugestellt: + typ (strom) = zustellung. + +wiederholen: + IF sendeeintrag + THEN + sendung wiederholen + ELSE + empfangseintrag freigeben + FI. + +sendeeintrag : vx.quellrechner = own . + +sendung wiederholen: + IF wiederholung noch sinnvoll + THEN + IF frisch + THEN + time out bei open + ELSE + datenteil wiederholen + FI + ELSE + sendung loeschen + FI. + +wiederholung noch sinnvoll: + task noch da AND bei call noch im call. + +task noch da: vx.quelle = collector OR exists (vx.quelle). + +bei call noch im call: + IF call aufruf + THEN + callee (vx.quelle) = vx.ziel + ELSE + TRUE + FI. + +frisch: vx.sequenz = -1. + +time out bei open: + IF vx.sendecode > -4 OR opentry (strom) > 0 + THEN + open wiederholen ; + opentry (strom) DECR 1 + ELSE + nak an quelle senden + FI. + +nak an quelle senden: + dr := nilspace; + BOUND TEXT VAR erm := dr; + erm := "Station "+text(vx.zielrechner)+" antwortet nicht"; + snr := strom; + q := vx.ziel; + z := vx.quelle; + ant := error nak; + sendung loeschen; + LEAVE zeitueberwachung . + +open wiederholen: + sendereport ("wdh open"); + IF opentry (strom) > 0 THEN zeit(strom) := 4 ELSE zeit(strom) := 40 FI; + openblock := vx; + openblock.head := stx open; + ab die post. + +datenteil wiederholen: + sendereport ("wdh data. sqnr "+text (vx.sequenz)); + senden . + +empfangseintrag freigeben: + IF antwort auf call + THEN + weiter warten + ELSE + empfangsreport ("Empfangseintrag freigegeben"); + loesche verbindung (strom) + FI. +antwort auf call: callee (vx.ziel) = vx.quelle. + +weiter warten: zeit (strom) := 400. + +END PROC zeitueberwachung; + +PROC sendereport (TEXT CONST txt): + report (text (strom)+":"+txt+". Absender: """+nam (vx.quelle)+ + """. Ziel "+text(vx.zielrechner) + " Taskindex: " + + text (index (vx.ziel))); +END PROC sendereport; + +PROC empfangsreport (TEXT CONST txt): + report (text (strom)+":"+txt+". Empfänger: """ + +nam (vx.ziel)+""". Quelle "+text (vx.quellrechner) + + " Taskindex: " + text (index (vx.quelle))); +END PROC empfangsreport ; + +PROC sendung loeschen: + strom loeschen (tasknr (vx.quelle)) +END PROC sendung loeschen; + +PROC strom loeschen (INT CONST tasknr): + IF callaufruf CAND alter call (tasknr ) = strom + THEN + alter call (tasknr ) := 0 + FI; + vx.strom := 0; + forget (vdr) +END PROC strom loeschen; + +PROC empfang loeschen: + quit zaehler INCR 1; + strom loeschen (tasknr (vx.ziel)) +END PROC empfang loeschen; + +PROC loesche verbindung (INT CONST nr): + strom := nr; + IF sendeeintrag + THEN + sendung loeschen + ELSE + gegenstelle zum loeschen auffordern; + empfang loeschen + FI. + +gegenstelle zum loeschen auffordern: + IF verbindung aktiv THEN quittieren (-loesche) FI. + +verbindung aktiv: vx.strom > 0. + +sendeeintrag: vx.quellrechner = own . + +END PROC loesche verbindung; + +PROC weiter senden: + IF NOT alles raus + THEN + sequenz zaehlung; + IF neue seite THEN seitennummer eintragen FI; + senden + FI. + +sequenz zaehlung: + vx.sequenz INCR 1. + +neue seite: + IF via node THEN (vx.sequenz AND packets per page via node minus 1) = 0 + ELSE (vx.sequenz AND pakete pro seite minus 1) = 0 + FI. + +seitennummer eintragen: + dr page (strom) := vx.seiten nummer; + vx.seitennummer := next ds page (vdr, dr page (strom)). + + +END PROC weiter senden; + +.packets per page: + + IF via node THEN packets per page via node + ELSE pakete pro seite + FI. + +packets per page minus 1: + IF via node THEN packets per page via node minus 1 + ELSE pakete pro seite minus 1 + FI. + +used length: + + IF via node THEN data len via node + ELSE nutzlaenge + FI. + +PROC senden: + INT VAR nl; + zeit(strom) := 6; + openblock := vx; + nl := used length; + transmit header (workspace); + vorspann senden; + daten senden; + transmit trailer. + +vorspann senden: + blockout (workspace, 1, dr verwaltungslaenge, vorspannlaenge). + +daten senden: + blockout (vdr,dr page (strom),distanz,nl). + +distanz: nl* (vx.sequenz AND packets per page minus 1). + +END PROC senden; + +PROC naechste verbindung vorbereiten: + FOR strom FROM 1 UPTO maxstrom REP + UNTIL vx.strom = 0 PER; + IF vx.strom <> 0 THEN errorstop ("Verbindungsengpass") FI. +END PROC naechste verbindung vorbereiten; + +PROC sendung starten (TASK CONST quelle, ziel, INT CONST code): + sendung starten (quelle,ziel, station(ziel), code) +END PROC sendung starten; + +PROC sendung starten (TASK CONST quelle, ziel, INT CONST ziel station,code): + IF ziel station = own + THEN + report ("Irrläufer: Sendung an eigene Station. Absender:"""+ + nam (quelle)+"""."); + vx.strom := 0; + forget (vdr) + ELSE + openblock.ziel := ziel; + openblock.quelle :=quelle; + openblock.sendecode := code; + openblock.zielrechner:= ziel station; + openblock.quellrechner :=own; + openblock.zwischenziel := route.zwischen (ziel station)+own256; + alten call loeschen (quelle); + IF call oder ping pong + THEN typ (strom) := call pingpong; call merken + ELSE typ (strom) := send wait FI; + sendung neu starten + FI. + +call oder pingpong: openblock.ziel = callee (openblock.quelle). + +call merken: alter call (tasknr (quelle)) := strom. + +END PROC sendung starten; + +PROC encode packet length (INT VAR val): + + IF val < 96 THEN + ELIF val < 160 THEN val DECR 32 + ELIF val < 288 THEN val DECR 128 + ELIF val < 544 THEN val DECR 352 + ELIF val < 1056 THEN val DECR 832 + ELIF val < 2080 THEN val DECR 1824 + FI; + rotate (val, 8) + +ENDPROC encode packet length; + +PROC sendung neu starten: + INT VAR value; + openblock.head:= stx open; + openblock.sequenz := -1; + openblock.seitennummer:= next ds page (vdr,-1); + openblock.strom := strom; + vx := open block; + schnelles nak bei routen liefern; + ab die post; + value := vorspannlaenge + used length; + encode packet length (value); + vx.head:=code stx+value. + +schnelles nak bei routen liefern: + IF openblock.sendecode = -routen liefern code + THEN + openblock.zwischenziel := openblock.zielrechner+own256; + zeit(strom) := 2; + opentry (strom) := 0 + ELSE + zeit (strom) :=8; + opentry (strom) := 2 + FI. + +END PROC sendung neu starten; . + +ab die post: + transmit header (workspace); + block out (work space,1, dr verwaltungslaenge,open laenge); + transmit trailer. + +PROC alten call loeschen (TASK CONST quelle): + IF alter call aktiv + THEN + INT VAR lstrom := strom; + vx:=openblock; + strom := alter call (tasknr (quelle)); + IF in ausfuehrungsphase + THEN + sendereport ("Call-Löschung vorgemerkt"); + loeschung vormerken + ELSE + report ("Call gelöscht."""+nam(quelle)+""". Strom "+text(strom)); + loesche verbindung (strom) + FI; + strom := lstrom; + openblock := vx + FI. + +in ausfuehrungsphase: + typ(strom) = call im wait OR typ (strom) = call in zustellung. + +loeschung vormerken: + typ(strom) := call im abbruch; + alter call (tasknr (quelle)) := 0. + + + alter call aktiv: + alter call (tasknr (quelle)) > 0. + +END PROC alten call loeschen; + +PROC packet eingang + ( INT VAR snr, TASK VAR q, z, INT VAR ant,DATASPACE VAR dr): + snr := 0; + fehlertest; + vorspann holen; + IF NOT ring logik THEN daten teil FI. + +ring logik: FALSE. + +fehlertest: +# + INT VAR c12; + control (12,0,0,c12); + IF c12 <> 0 + THEN + flush buffers; + report ("E/A-Fehler "+text (c12)); + control (12,0,0,c12); + LEAVE packet eingang + FI. + + #. + +vorspann holen: + sync; + IF NOT blockin (workspace, 1, dr verwaltungslaenge2, block laenge) + THEN LEAVE packeteingang + FI. + + +blocklaenge: IF code t > min data length + THEN + vorspannlaenge-2 + ELSE + code t -2 + FI. + +sync: + IF NOT packet start already inspected + THEN + TEXT VAR skipped, t:= ""; + skipped := next packet start; + IF skipped = "" THEN LEAVE packet eingang FI; + t := incharety (1); + code t := code (t); + ELSE + skipped := buffer first; + buffer first := ""; + t := incharety (1); + code t := code (t); + FI; + decode packet length; +IF skipped=stx AND laenge ok THEN LEAVE sync FI; + REP + skipped CAT t; + t := incharety (1); (* next character *) + IF t = "" THEN + report ("skipped",skipped); + LEAVE packet eingang + FI ; + codet := code (t); + UNTIL blockanfang OR length (skipped) > 200 PER; + decode packet length; + IF skipped <> stx THEN report ("skipped bei sync:", skipped) FI. + +decode packet length: + +IF code t < 96 THEN + ELIF code t < 128 THEN code t INCR 32 + ELIF code t < 160 THEN code t INCR 128 + ELIF code t < 192 THEN code t INCR 352 + ELIF code t < 224 THEN code t INCR 832 + ELIF code t < 256 THEN code t INCR 1824 +FI. + +packet start already inspected: buffer first <> "". + +blockanfang: + (skipped SUB length(skipped)) = stx AND laenge ok. + +laenge ok: + (codet = datenpacketlaenge OR codet = datenpacketlaenge via node + OR codet = ack laenge OR code t = openlaenge). + +zielnummer: vorspann.zielrechner. + +daten teil: + IF zielnummer = own + THEN + ziel erreicht (openblock,snr,q,z,ant,dr) + ELSE + weiter faedeln + FI. + +weiter faedeln: + INT VAR value; + IF zielrechner ok + THEN + IF neue verbindung + THEN + IF (openblock.sendecode = -routenlieferncode) OR NOT route ok + THEN LEAVE packet eingang + FI + FI; + value := code t; + encode packet length (value); + vorspann.head := code stx + value; + vorspann.zwischenziel := own256 + route.zwischen (vorspann.zielrechner); + nutzdaten einlesen; + dr := workspace; + snr := 1000; + ant := zielnummer + FI. + +nutzdaten einlesen: + IF code t > data len via node + THEN + IF NOT blockin (workspace, 1, drverwaltungslaenge+vorspannlaenge, data len via node) + THEN + LEAVE packeteingang + FI; + IF NOT next packet ok THEN LEAVE packeteingang FI + FI. + +END PROC packet eingang; + +PROC ziel erreicht (STEUER CONST prefix, + INT VAR snr, TASK VAR q, z, INT VAR ant,DATASPACE VAR dr): + last data := -1; + IF NOT quellrechner ok + THEN + report ("Quellrechner "+text(prefix.quellrechner)); + LEAVE ziel erreicht + FI; + IF neue verbindung + THEN + IF NOT route ok OR NOT quelltask ok + THEN report ("verbotene Route: " + text (prefix.quellrechner)); + LEAVE ziel erreicht + FI; + verbindung bereitstellen + ELIF quittung + THEN + strom := ack packet.strom; + IF falsche stromnummer THEN report ("Strom falsch in Quittung"); + LEAVE ziel erreicht FI; + IF vx.strom = 0 THEN LEAVE ziel erreicht FI; + IF ackpacket.code >= ok THEN weiter senden + ELIF NOT route ok THEN + sendereport ("verbotene Route bei Quittung"); + LEAVE ziel erreicht + ELIF ackpacket.code = -von vorne THEN + sendereport ("Neustart"); + openblock := vx; + sendung neu starten + ELIF ackpacket.code = -wiederhole THEN back 16 + ELIF ackpacket.code = -loesche THEN fremdloeschung + ELIF ackpacket.code = -beende AND alles raus THEN strom abschliessen + FI + ELIF verbindung festgestellt + THEN + zeit(strom) := 400; + opti := vx; + datenpacket + ELSE + strom := maxstrom1; + vx:=prefix; + report ("Daten ohne Eroeffnung von " +text(prefix.quellrechner) + +" Sequenznr "+text(prefix.sequenz)); + daten entfernen (used length); + IF alles raus THEN quittieren (-beende) ELSE quittieren(-von vorne) FI + FI. + +quelltask ok: + prefix.quelle = collector OR antwort auf routen liefern + OR station (prefix.quelle) = prefix.quellrechner. + +antwort auf routen liefern: prefix.quelle = myself. + +verbindung bereitstellen: + IF (prefix.sendecode < 0 OR station (prefix.ziel) = own) + AND quellrechner ok + THEN + freie verbindungsnummer; + vdr := nilspace; + vx := open block; + zeit(strom) := 30; + quittieren falls genug pufferplatz; + vx.sequenz := 0 ; + opti := vx; + dr page (strom) :=-2; + IF abschluss THEN rueckmeldung FI + FI. + +loeschung vorgemerkt: typ(strom) = call im abbruch. + +strom abschliessen: + IF call aufruf + THEN + wdh data vor ablauf der zustellversuche bei der gegenstation; + ausfuehrungsphase merken + ELSE + wdh data sperren + FI. + +wdh data sperren: + zeit (strom) := 12000. + +wdh data vor ablauf der zustellversuche bei der gegenstation: + zeit (strom) := 80. + +ausfuehrungsphase merken: typ(strom) := call in zustellung. + +back16: + datenraum etwas rueckspulen; + opentry (strom) := 2; + nicht sofort senden (* wegen vagabundierender Quittungen *). + +nicht sofort senden: zeit(strom) := 2. + +datenraum etwas rueckspulen: + INT VAR pps := packets per page ; + sendereport ("etwas rueckgespult"); + INT VAR vs :=-1; + dr page (strom) := -1; + INT VAR i; + FOR i FROM 1 UPTO vx.sequenz DIV pps - etwas REP + vs INCR pps; + dr page (strom) := next ds page (vdr, dr page (strom)) + PER; + vx.seiten nummer := next ds page (vdr, dr page (strom)) ; + vx.sequenz := vs. + +etwas: 3. + +fremdloeschung: + IF fremdrechner ok und sendung + THEN + IF typ (strom) = call in zustellung + THEN + typ (strom) := call im wait + ELSE + IF NOT alles raus + THEN + sendereport ("Sendung von Gegenstelle geloescht") + FI; + sendung loeschen + FI + FI. + +fremdrechner ok und sendung: + ackpacket.quellrechner = vx.zielrechner . + + +quittieren falls genug pufferplatz: + IF quit zaehler > 0 THEN + quit zaehler DECR 1; + open quittieren; + block vorab quittieren + ELSE + quittieren (-wiederhole) + FI. + +open quittieren: quittieren (ok). +block vorab quittieren: + IF prio (myself) < 3 THEN quittieren (ok) FI. + +quittung: code t <= ack laenge. + + +verbindung festgestellt: + FOR strom FROM maxstrom DOWNTO 1 REP + IF bekannter strom + THEN LEAVE verbindung festgestellt WITH TRUE FI + PER; + FALSE. + +bekannter strom: + vx.strom = prefix.strom AND vom selben rechner. + +vom selben rechner: + vx.quellrechner = prefix.quellrechner. + +daten: + IF neue seite da THEN check for valid pagenr; + dr page(strom) := prefix.seitennummer; + ELIF prefix.seitennummer < dr page(strom) + THEN empfangsreport ("Falsche Seitennummer, Soll: " + + text(drpage(strom)) + " ist: " + + text (prefix.seitennummer) + + " bei Sequenznr: " + + text(prefix.sequenz)); + flush buffers; + quittieren (- wiederhole); + LEAVE ziel erreicht + FI; + sequenz zaehlung; + IF neue seite kommt + THEN + vx.seiten nummer := prefix.seiten nummer; + dr page(strom) := prefix.seitennummer; + FI; + quittieren(ok); + IF NOT blockin (vdr, opti.seiten nummer, distanz, nl) + COR NOT next packet ok + THEN quittieren (-wiederhole); + LEAVE ziel erreicht + FI; + last data := strom. + +check for valid pagenr: + IF prefix.seitennummer < dr page(strom) AND prefix.seitennummer > -1 + THEN report ("Absteigende Seitennummern, alt: " + text(drpage(strom))+ + " neu: "+ text(prefix.seitennummer) + " Seq.nr: " + + text(vx.sequenz) ) ; + flush buffers; + quittieren (- von vorne); + LEAVE ziel erreicht; + FI. + +datenpacket: + INT VAR nl := used length; + INT VAR pps1 := packets per page minus 1; + IF sendung wartet auf zustellung THEN auffrischen ELSE daten holen FI. + +sendung wartet auf zustellung: typ (strom) = zustellung. + +auffrischen: zeit (strom) := 200; daten entfernen (nl). + +daten holen: + IF opti.sequenz >= prefix.sequenz AND opti.sequenz < prefix.sequenz+100 + AND prefix.sequenz >= 0 + THEN + IF opti.sequenz <> prefix.sequenz + THEN empfangsreport ("Sequenzreset von "+text(opti.sequenz)+" auf "+ + text (prefix.sequenz)); + vx.sequenz := prefix.sequenz; + IF pagenumber ok + THEN dr page (strom) := prefix.seitennummer + ELSE empfangsreport ("Blocknummer falsch, neu: "+ + text (prefix.seitennummer) + ", alt : " + + text (drpage(strom)) ); + FI; + vorabquittung regenerieren + FI; + daten ; + IF abschluss THEN rueckmeldung FI; + ELSE + empfangsreport ("Sequenzfehler: soll "+text(vx.sequenz)+" ist "+ + text(prefix.sequenz)); + quittieren (-wiederhole); + daten entfernen (nl) + FI. + +pagenumber ok: + dr page (strom) >= prefix.seitennummer . + +rueckmeldung: + snr := strom; + q := vx.quelle; + z := vx.ziel; + ant := vx.sendecode; + dr := vdr; + LEAVE ziel erreicht. + +vorabquittung regenerieren: + IF prio (myself) < 3 + THEN + quittieren (ok) + FI. + +distanz: (opti.sequenz AND pps1 ) * nl. + +sequenz zaehlung: + vx.sequenz INCR 1. + +neue seite da: + neue seite kommt. + +neue seite kommt: +(vx.sequenz AND pps1) = 0. + +freie verbindungsnummer: + INT VAR h strom :=maxstrom1, cstrom := 0; + FOR strom FROM 1 UPTO maxstrom REP + IF vx.strom = 0 THEN h strom := strom ; + typ(strom) := send wait + ELIF bekannter strom + THEN empfangsreport ("Reopen"); + quit zaehler INCR 1; + IF typ (strom) = zustellung THEN typ (strom) := send wait FI; + forget (vdr); + LEAVE freie verbindungsnummer + ELIF antwort auf call + THEN + IF loeschung vorgemerkt + THEN + vx := prefix; + loesche verbindung (strom); + LEAVE ziel erreicht + FI; + cstrom := strom; + typ (strom) := call pingpong; + forget (vdr); + FI + PER; + IF cstrom > 0 THEN strom := cstrom ELSE strom := h strom FI; + IF strom = maxstrom1 THEN + vx:=prefix; + empfangsreport ("Verbindungsengpass"); + quittieren (-wiederhole); + LEAVE ziel erreicht + FI. + +antwort auf call: + prefix.sendecode >= 0 AND + call aufruf AND vx.quelle = prefix.ziel AND vx.ziel = prefix.quelle. + +END PROC ziel erreicht; + +PROC daten entfernen (INT CONST wieviel): + BOOL VAR dummy ; + dummy:=blockin (workspace, 2, 0, wieviel) +END PROC daten entfernen; + +BOOL PROC route ok: + INT VAR zwischenquelle := vorspann.zwischenziel DIV 256, + endquelle := vorspann.quellrechner; + zwischenquelle abgleichen; + endquelle abgleichen; + TRUE. + +zwischenquelle abgleichen: + IF NOT zwischenroute gleich + THEN + IF NOT zwischenabgleich erlaubt THEN LEAVE route ok WITH FALSE FI; + route.port (zwischenquelle) := channel; + route.zwischen (zwischenquelle) := zwischenquelle; + abgleich (zwischenquelle, zwischenquelle) + FI. + +zwischenabgleich erlaubt: route.port (zwischenquelle) < 256. + +endquelle abgleichen: + IF NOT endroute gleich + THEN + IF NOT endabgleich erlaubt THEN LEAVE route ok WITH FALSE FI; + route.port (endquelle) := channel; + route.zwischen (endquelle) := zwischenquelle; + abgleich (endquelle, zwischenquelle) + FI. + +endabgleich erlaubt: route.port (endquelle) < 256. + +zwischenroute gleich: + (route.port (zwischenquelle) AND 255) = channel + AND + route.zwischen (zwischenquelle) = zwischenquelle. + +endroute gleich: + (route.port (endquelle) AND 255) = channel + AND + route.zwischen (endquelle) = zwischenquelle. + +END PROC route ok; + +BOOL PROC abschluss: + + last data := -1; + IF neue seite kommt AND vx.seiten nummer = -1 + THEN + quittieren (-beende); + an ziel weitergeben + ELSE + FALSE + FI. +neue seite kommt: +(vx.sequenz AND packets per page minus 1) = 0. + +an ziel weitergeben: + IF tasknummerfrage THEN taskfrage beantworten ;pufferplatz ; FALSE + ELIF tasknamenfrage THEN name senden ;pufferplatz ; FALSE + ELIF taskinfofrage THEN task info senden;pufferplatz ; FALSE + ELIF routenfrage THEN routen senden; pufferplatz; FALSE + ELSE senden ; TRUE + FI. + +pufferplatz : quitzaehler INCR 1 . + +senden: + IF callaufruf + THEN + ein versuch (* bei Antwort auf Call muß ein Zustellversuch reichen *) + ELSE + max 100 versuche; + typ (strom) := zustellung + FI. + +tasknummerfrage:opti.sendecode = -taskid code. + +tasknamenfrage: opti.sendecode = -name code. + +taskinfofrage: opti.sendecode = -task info code. + +routenfrage: opti.sendecode = -routen liefern code. + +max 100 versuche: zeit(strom) := 100. + +ein versuch: zeit (strom) := 1. + +taskfrage beantworten: + disable stop; + BOUND TEXT VAR tsk := vdr; + TEXT VAR save tsk := tsk; + forget (vdr); vdr := nilspace; + BOUND TASK VAR task id := vdr; + task id := task(save tsk); + IF is error THEN + clear error; enable stop; + forget (vdr); vdr := nilspace; + BOUND TEXT VAR errtxt := vdr; + errtxt := text(own)+"/"""+save tsk+""" gibt es nicht"; + sendung starten (collector, opti.quelle, 2) + ELSE + enable stop; + sendung starten (collector, opti.quelle, 0) + FI. + +name senden: + quittieren (-loesche); + forget (vdr); vdr := nilspace; + tsk := vdr; + tsk := nam (opti.ziel); + sendung starten (collector, opti.quelle, 0). + +routen senden: + forget (vdr); vdr := old ("port intern"); + sendung starten (opti.ziel, opti.quelle, 0). + +task info senden: + disable stop; + BOUND INT VAR ti code := vdr; + INT VAR ti cd := ti code; + forget (vdr); vdr := nilspace; + FILE VAR task inf := sequential file (output,vdr); + head line (task inf,"Station "+text(own)); + task info (ti cd, task inf); + IF is error + THEN + forget (vdr); vdr := nilspace; + errtxt := vdr; + errtxt := errormessage; + clear error; + sendung starten (collector, opti.quelle, 2) + ELSE + sendung starten (collector,opti.quelle,0) + FI; + enable stop +END PROC abschluss ; + +PROC quittieren(INT CONST code) : + INT VAR quell := vx.quellrechner ; + transmitted ackpacket := ACK:(stx quit, route.zwischen (quell)+own256, quell, own, + vx.strom, code); + transmit header (transmitted ack space); + blockout (transmitted ack space,1,dr verwaltungslaenge, ack laenge); + transmit trailer; +END PROC quittieren; + +BOOL PROC next packet ok: + buffer first := next packet start; + buffer first = "" COR normal packet start. + +normal packet start: + IF buffer first = stx + THEN + TRUE + ELSE + buffer first := ""; flush buffers; FALSE + FI. + +END PROC next packet ok; +END PACKET basic net; + + diff --git a/system/net/1.8.7/src/net files-M b/system/net/1.8.7/src/net files-M new file mode 100644 index 0000000..ae6f9f3 --- /dev/null +++ b/system/net/1.8.7/src/net files-M @@ -0,0 +1,5 @@ +net report +net hardware interface +basic net +net manager + diff --git a/system/net/1.8.7/src/net hardware interface b/system/net/1.8.7/src/net hardware interface new file mode 100644 index 0000000..4e3466a --- /dev/null +++ b/system/net/1.8.7/src/net hardware interface @@ -0,0 +1,389 @@ +PACKET net hardware + +(************************************************************************) +(**** Netzprotokoll Anpassung *) +(**** Komplette Version mit BUS Anpassung 10.06.87 *) +(**** mit I/0 Controls fuer integrierte Karten *) +(**** Verschiedene Nutztelegrammgrössen *) +(**** Version: GMD 2.0 A.Reichpietsch *) +(************************************************************************) + + DEFINES + blockin, + blockout, + set net mode, + net address, + mode text, + data length, + data length via node, + decode packet length, + next packet start, + flush buffers, + transmit header, + transmit trailer, + version, + reset box, + max mode, + net mode: + + + + + LET eak prefix laenge = 6, + packet length before stx = 14 (*eth header =14 *), + maximum mode nr = 12, + stx = ""2"", + niltext = "", + null = "0", + hex null = ""0"", + blank = " ", + eak prefix = ""0""0""0""0"", + typefield = "EU", + prefix adresse = "BOX", + second prefix adresse = ""0"BOX", + second address type bound = 90; + + INT CONST data length via node :: 64; + TEXT CONST version :: "GMD 2.0 (10.6.87)"; + + + TEXT VAR own address; + INT VAR paketlaenge, eumel paket laenge, mode, rahmenlaenge, actual data length; + +BOOL PROC blockin (DATASPACE VAR ds, INT CONST seite, abstand, laenge): + INT VAR hilfslaenge:=laenge, code:= abstand+laenge+512; + REAL VAR time out := clock (1) + 10.0; + REP + blockin (ds,seite,code-hilfslaenge, hilfslaenge, hilfslaenge); + UNTIL hilfslaenge = 0 OR clock (1) > time out PER ; + IF hilfslaenge <> 0 + THEN report ("blockin abbruch, fehlende Zeichen: "+text(hilfslaenge)); + FI; + hilfslaenge = 0 +END PROC blockin; + +PROC blockout (DATASPACE CONST ds, INT CONST seite, abstand, laenge): + INT VAR hilfslaenge:=laenge, code:= abstand+laenge+512; + REP + blockout (ds,seite,code-hilfslaenge, hilfslaenge, hilfslaenge); + UNTIL hilfslaenge = 0 PER +END PROC blockout; + +PROC set net mode (INT CONST new mode): + mode := new mode ; + own address := net address (station(myself)); + SELECT mode OF + CASE 1,3 : set data length (64); + CASE 2 : std framelength; set data length (64) + CASE 4,6 : set data length (128) + CASE 5 : std framelength; set data length (128) + CASE 7,9 : set data length (256) + CASE 8 : std framelength; set data length (256) + CASE 10,12 : set data length (512) + CASE 11 : std framelength; set data length (512); + + OTHERWISE + END SELECT. + + std framelength: + rahmenlaenge := eak prefix laenge + packet length before stx. + +ENDPROC set net mode; + +INT PROC max mode: + maximum mode nr +ENDPROC max mode; + +INT PROC net mode: + mode +ENDPROC net mode; + +TEXT PROC mode text: + mode text (mode) +ENDPROC mode text; + +TEXT PROC mode text (INT CONST act mode): + SELECT act mode OF + CASE 1: "Modus: (1) EUMEL-Netz 64 Byte" + CASE 2: "Modus: (2) ETHERNET via V.24 64 Byte" + CASE 3: "Modus: (3) ETHERNET integrated 64 Byte" + CASE 4: "Modus: (4) EUMEL-Netz 128 Byte" + CASE 5: "Modus: (5) ETHERNET via V.24 128 Byte" + CASE 6: "Modus: (6) ETHERNET integrated 128 Byte" + CASE 7: "MODUS: (7) EUMEL-Netz 256 Byte" + CASE 8: "MODUS: (8) ETHERNET via V.24 256 Byte" + CASE 9: "MODUS: (9) ETHERNET integrated 256 Byte" + CASE 10: "MODUS: (10) EUMEL-Netz 512 Byte" + CASE 11: "MODUS: (11) ETHERNET via V.24 512 Byte" + CASE 12: "MODUS: (12) ETHERNET integrated 512 Byte" + OTHERWISE errorstop ("Modus " + text(mode) + " gibt es nicht"); + error message + END SELECT + +ENDPROC mode text; + +PROC set data length (INT CONST new data length): + actual data length := new data length +ENDPROC set data length; + +INT PROC data length: + actual data length +ENDPROC data length; + +PROC reset box (INT CONST net mode): + SELECT net mode OF + CASE 1,4,7,10 : eumel net box reset + CASE 2,5,8,11 : eak reset + OTHERWISE controler reset + END SELECT. + + eumel net box reset: + out (90*""4""); + REP UNTIL incharety (1) = niltext PER. + + eak reset: + out ("E0"13"E0"13""). + + controler reset: + INT VAR dummy; + control (-35, 0,0,dummy); + control (22,0,0,dummy). + +ENDPROC reset box; + +PROC remove frame + (TEXT VAR erstes zeichen vom eumel telegramm, BOOL VAR kein telegramm da): + kein telegramm da := FALSE; + SELECT net mode OF + CASE 2,5,8,11 : remove ethernet frame + (erstes zeichen vom eumel telegramm, kein telegramm da) + OTHERWISE + END SELECT; +ENDPROC remove frame; + +PROC remove ethernet frame (TEXT VAR string, BOOL VAR schrott): + TEXT VAR speicher, t; + INT VAR lg; + + t := string; + speicher := niltext; + WHILE kein stx da REP + lies zeichen ein; + teste auf timeout; + UNTIL textoverflow PER; + melde eingelesene zeichen. + + lies zeichen ein: + speicher CAT t; + t := incharety (1). + + teste auf timeout: + IF t = niltext THEN schrott := (speicher <> niltext) + CAND not only fill characters; + string := niltext; + LEAVE remove ethernet frame + FI. + + not only fill characters: + pos (speicher, ""1"", ""254"",1) <> 0. + + kein stx da : + t <> stx. + + textoverflow: + length (speicher) > 1000. + + melde eingelesene zeichen: + IF kein stx da + THEN kein eumeltelegrammanfang + ELSE untersuche ethernet header + FI. + + kein eumeltelegrammanfang: + report ("skipped ,fehlendes ,letztes Zeichen:", t); + string := t; + schrott := TRUE. + + untersuche ethernet header: + string := t; + IF ethernet header inkorrekt + THEN melde fehler + FI. + + ethernet header inkorrekt: + lg := length (speicher); + packet zu kurz COR adresse falsch. + + packet zu kurz: + lg < packet length before stx. + + adresse falsch: + INT VAR adrpos := pos (speicher, own address); + zieladresse falsch COR adresse nicht an der richtigen pos . + + zieladresse falsch: + adrpos < 1. + + adresse nicht an der richtigen pos: + adrpos <> lg - packet length before stx + 1. + + melde fehler: + report ("Header inkorrekt eingelesen: ", speicher + t); + string := t; + schrott := TRUE. + +ENDPROC remove ethernet frame; + +TEXT PROC next packet start: + + TEXT VAR t := niltext; + BOOL VAR schrott := FALSE; + + t:= incharety (1); + IF t = niltext THEN LEAVE next packet start WITH niltext + ELSE remove frame (t, schrott) + FI; + IF schrott THEN no stx or niltext + ELSE t + FI. + + no stx or niltext: + IF t = stx THEN "2" + ELIF t = niltext THEN "0" + ELSE t + FI. + +ENDPROC next packet start; + +PROC flush buffers: + REP UNTIL incharety (5) = niltext PER; + report ("buffers flushed"); +ENDPROC flush buffers; + +PROC transmit header (DATASPACE CONST w): + BOUND INT VAR laengeninformation := w; + eumel paket laenge := laengeninformation ; + decode packet length (eumel paket laenge); + SELECT net mode OF + CASE 1,4,7,10 : + CASE 2,5,8,11 : eak und eth header senden (w) + OTHERWISE : telegrammanfang melden; + std ethernet header senden (w) + END SELECT; + +ENDPROC transmit header; + +PROC decode packet length (INT VAR decoded length): + + decoded length DECR 2; + rotate (decoded length, 8); + + IF decoded length < 96 THEN + ELIF decoded length < 128 THEN decoded length INCR 32 + ELIF decoded length < 160 THEN decoded length INCR 128 + ELIF decoded length < 192 THEN decoded length INCR 352 + ELIF decoded length < 224 THEN decoded length INCR 832 + ELIF decoded length < 256 THEN decoded length INCR 1824 + FI; + +ENDPROC decode packet length; + +PROC transmit trailer: + INT VAR dummy; + SELECT net mode OF + CASE 3,6,9,12 : control (21,0,0,dummy) + OTHERWISE + END SELECT. + +ENDPROC transmit trailer; + +PROC std ethernet header senden (DATASPACE CONST x): + TEXT VAR eth adresse, ethernet kopf := niltext; + INT VAR adresse; + BOUND STRUCT (INT head, zwischennummern) VAR header := x; + zieladresse holen; + zieladresse senden; + quelladresse senden; + typfeld senden; + ausgeben. + + zieladresse holen: + adresse := header.zwischennummern AND 255; + eth adresse := net address (adresse). + + zieladresse senden: + ethernetkopf CAT eth adresse. + + quelladresse senden: + ethernetkopf CAT own address. + + typfeld senden: + ethernetkopf CAT typefield. + + ausgeben: + out (ethernetkopf). + +ENDPROC std ethernet header senden; + +PROC telegrammanfang melden: + INT VAR dummy; + control (20,eumel paket laenge + packet length before stx,0, dummy). + +ENDPROC telegrammanfang melden; + +PROC eak und eth header senden (DATASPACE CONST x): + TEXT VAR res:= niltext; + + neue laenge berechnen; + eak kopf senden; + std ethernet header senden (x). + + neue laenge berechnen: + paket laenge := rahmenlaenge + eumel paket laenge. + + eak kopf senden: + res := code (paket laenge DIV 256); + res CAT (code (paket laenge AND 255)); + res CAT eak prefix; + out(res). + +ENDPROC eak und eth header senden; + +TEXT PROC net address (INT CONST eumel address): + TEXT VAR res ; + INT VAR low byte; + +SELECT mode OF + CASE 1,4,7,10 : eumel net address + OTHERWISE ethernet address +END SELECT. + +eumel net address: + text(eumel address). + +ethernet address: + IF second adress kind THEN second eth header + ELSE first eth header + FI; + res. + + second adress kind: + eumel address = 34 COR + eumel address > second address type bound. + + second eth header: + low byte := eumel address AND 255; + res := second prefix adresse + code (low byte); + res CAT hex null. + + first eth header: + res := prefix adresse + text (eumel address, 3); + changeall (res, blank, null). + +ENDPROC net address; + +ENDPACKET net hardware; + + + + diff --git a/system/net/1.8.7/src/net inserter b/system/net/1.8.7/src/net inserter new file mode 100644 index 0000000..c89d0f0 --- /dev/null +++ b/system/net/1.8.7/src/net inserter @@ -0,0 +1,145 @@ +(*************************************************************************) +(*** Insertiert alle notwendigen Pakete, die zum Betrieb des Netzes ***) +(*** notwendig sind. ***) +(*** Berücksichtigt nur EUMEL - Versionen ab 1.8.1, sowie ***) +(*** Multi-User-Version ***) +(*** ***) +(*** ***) +(*** 23.05.87 ar ***) +(*************************************************************************) + +LET netfile = "netz", + multi files = "net files/M"; + + +INT CONST version :: id (0); +THESAURUS VAR tesa; + +head; +IF no privileged task + THEN errorstop (name (myself) + " ist nicht privilegiert!") + ELIF station number wrong + THEN errorstop ("'define station' vergessen ") +FI; + +IF version < 181 THEN versionsnummer zu klein + ELSE install net +FI. + +no privileged task: + NOT (myself < supervisor). + +station number wrong: + station (myself) < 1. + +install net : + IF NOT exists (netfile) + THEN errorstop ("Datei " + netfile +" existiert nicht") + FI; + IF is multi THEN insert multi net + ELSE errorstop ("Diese Netzversion ist nur für Multi-user Versionen freigegeben") + FI; + forget ("net install", quiet); + net start. + +net start : + say line (" "); + do ("start"); + do ("global manager (PROC (DATASPACE VAR, INT CONST, INT CONST, TASK CONST) + net manager)"). + +is multi : + (pcb(9) AND 255) > 1. + +insert multi net : + hole dateien vom archiv; + insert say and forget (tesa). + +hole dateien vom archiv : + fetch if necessary (multi files); + tesa := ALL (multi files); + forget (multi files, quiet); + fetch if necessary (tesa - all); + say line (" "); + say line ("Archiv-Floppy kann entnommen werden."); + release (archive). + + +head : + IF online THEN page; + put center (" E U M E L - Netz wird installiert."); + line; + put center ("----------------------------------------"); + line (2) + FI. + +versionsnummer zu klein : + errorstop ("Netzsoftware erst ab Version 1.8.1 insertierbar !"). + +PROC fetch if necessary (TEXT CONST datei) : + IF NOT exists (datei) THEN say line ("Loading """ + datei + """..."); + fetch (datei, archive) + FI. +END PROC fetch if necessary; + +PROC fetch if necessary (THESAURUS CONST tes) : + do (PROC (TEXT CONST) fetch if necessary, tes) +END PROC fetch if necessary; + +PROC insert say and forget (TEXT CONST name of packet): + IF online THEN INT VAR cx, cy; + put ("Inserting """ + name of packet + """..."); + get cursor (cx, cy) + FI; + insert (name of packet); + IF online THEN cl eop (cx, cy); line FI; + forget (name of packet, quiet) +END PROC insert say and forget; + +PROC insert say and forget (THESAURUS CONST tes): + do (PROC (TEXT CONST) insert say and forget, tes) +END PROC insert say and forget; + +PROC put center (TEXT CONST t): + put center (t, xsize); +END PROC put center; + +PROC put center (INT CONST zeile, TEXT CONST t): + put center (zeile, t, xsize); +END PROC put center; + +PROC put center (TEXT CONST t, INT CONST gesamtbreite): + INT VAR cy; + get cursor (cy, cy); + put center (cy, t, gesamtbreite) +END PROC put center; + +PROC put center (INT CONST zeile, TEXT CONST t, INT CONST gesamtbreite): + cursor ((gesamtbreite - length (t)) DIV 2, zeile); + put (t). +END PROC put center; + +PROC cl eol: + out (""5"") +END PROC cl eol; + +PROC cl eop: + out (""4"") +END PROC cl eop; + +PROC cl eol (INT CONST cx, cy): + cursor (cx, cy); + cl eol +END PROC cl eol; + +PROC cl eop (INT CONST cx, cy): + cursor (cx, cy); + cl eop +END PROC cl eop; + +PROC say line (TEXT CONST t): + IF online THEN put line (t) FI +ENDPROC say line; + + + diff --git a/system/net/1.8.7/src/net manager b/system/net/1.8.7/src/net manager new file mode 100644 index 0000000..05f530e --- /dev/null +++ b/system/net/1.8.7/src/net manager @@ -0,0 +1,797 @@ +PACKET net manager DEFINES stop,net manager,frei, routen aufbauen, + (* 175 net manager 8 (!) *) + start, + definiere netz, + aktiviere netz, + list option, + erlaube, sperre, starte kanal, routen: + +TEXT VAR stand := "Netzsoftware vom 10.06.87 "; + (*Heinrichs *) +LET + maxstat = 127, + ack = 0, +(* nak = 1, *) + error nak = 2, +(* zeichen eingang = 4, *) + list code = 15, +(* fetch code = 11, *) + freigabecode = 29, + tabellencode = 500, + continue code = 100, + erase code = 14, + report code = 99, + abgleichcode = 98, + neue routen code = 97, + dr verwaltungslaenge = 8, + + (* Codes der Verbindungsebene *) + + task id code = 6, + name code = 7, + task info code = 8, + routen liefern code = 9, + + (* Weitergabecodes für Netzknoten *) + + route code = 1001, + out code = 1003, + + (* Typen von Kommunikationsströmen *) + + zustellung = 1, + call im wait = 3, + call im abbruch = 4, + call in zustellung = 5; + +LET STEUER = + STRUCT ( + INT head, + zwischenziel, + zielrechner, + quellrechner, + strom, + INT sequenz, + seiten nummer, + TASK quelle,ziel, + INT sende code); + +LET INFO = STRUCT (STEUER steuer, INT typ,maxseq); + +LET PARA = STRUCT (TASK quelle, ziel, INT sendecode, zielstation); + + +TASK VAR sohn; +INT VAR strom,c,kanalmode, rzaehler := 20; +BOUND STRUCT (ROW maxstat INT port, + ROW maxstat INT zwischen) VAR route; + + +TASK PROC netport (INT CONST ziel): + INT VAR kan := route.port (ziel) AND 255; + IF kan < 1 OR kan > 15 + THEN + niltask + ELSE + IF NOT exists (nettask (kan)) + THEN + access catalogue; + nettask (kan) := task (kan); + IF NOT (nettask (kan) < father) THEN nettask (kan) := niltask FI; + FI; + nettask (kan) + FI +END PROC netport; + +PROC frei (INT CONST stat,lvl): + DATASPACE VAR ds := nilspace; + BOUND STRUCT (INT x,y) VAR msg := ds; + msg.x := stat; msg.y := lvl; + INT VAR return; + call (netport (stat), freigabecode, ds, return) ; + forget (ds) +END PROC frei; + +PROC net manager (DATASPACE VAR ds, INT CONST order, phase, TASK CONST + ordertask): + + IF order = report code AND ordertask < myself + THEN + IF storage (old("report")) > 20 THEN forget ("report", quiet) FI; + FILE VAR rp := sequential file (output, "report"); + BOUND TEXT VAR rpt := ds; + putline (rp, rpt); + send (ordertask, ack, ds) + ELIF order = abgleichcode AND ordertask < myself + THEN + BOUND STRUCT (INT ende, zwischen) VAR x := ds; + route.port (x.ende) := channel (ordertask); + route.zwischen (x.ende) := x.zwischen; + send (ordertask, ack, ds) + ELIF order = neue routen code AND ordertask < myself + THEN + forget ("port intern"); + copy (ds,"port intern"); + route := old ("port intern"); + send (ordertask, ack, ds) + ELIF station (ordertask) = station (myself) + THEN + IF ordertask < myself + OR order = list code + OR order > continue code + THEN + IF order = list code + THEN + enable stop; + forget (ds); ds := old ("report"); + FILE VAR ff := sequential file (output,ds); + putline (ff,"bekannte Stationen:"); + stationen; line (ff); putline (ff,"--------"); + putline (ff,"Eingestellte Netzmodi:"); + kanaele ; + paketgroessen; + line (ff); putline (ff,"********"); + putline (ff,stand); + putline (ff,"Rechner "+text(station(myself))+" um "+time of day); + send (ordertask, ack, ds) + ELSE + free manager (ds,order,phase,order task) + FI + ELSE + errorstop ("nur 'list' ist erlaubt") + FI + FI . + +stationen: +INT VAR stat; +INT VAR mystation := station (myself); +FOR stat FROM 1 UPTO maxstat REP + IF route.port (stat) > 0 AND stat <> mystation + THEN + put (ff,text(stat)+"("+text (route.port (stat) AND 255)+","+ + text(route.zwischen(stat))+")") + FI +PER. + +paketgroessen: + + line(ff); + put (ff, "Nutzlaenge bei indirekter Verbindung "+ + text (data length via node) + " Byte "); line (ff). + +kanaele: + INT VAR portnummer; + TASK VAR tsk; + FOR portnummer FROM 1 UPTO 15 REP + tsk := task (portnummer); + IF tsk < myself THEN beschreibe kanal FI; + PER. + +beschreibe kanal: + putline (ff, name (tsk) + " haengt an Kanal " + text (channel (tsk)) + + ", " + mode text (netz mode (portnummer))). + +END PROC net manager; + +TASK VAR cd,stask; +ROW maxstat INT VAR erlaubt; + +PROC communicate: + enable stop; + INT VAR scode, merken :=0; + DATASPACE VAR dr := nilspace; + neuer start (quit max, kanalmode); +REP + forget (dr); + telegrammfreigabe; + wait (dr, scode, stask); + cd := collected destination; + IF weiterleitung steht noch aus + THEN + send (netport (merken), out code, mds, reply); + IF reply <> -2 THEN forget (mds); merken := 0 FI + FI; + IF zeichen da OR zeit abgelaufen + THEN + packet + ELIF cd = myself + THEN + netz info und steuerung + ELSE + sendung untersuchen (stask, cd, scode, dr) + FI +PER. + +telegrammfreigabe: + INT VAR dummy; + control (22,0,0,dummy). + +zeichen da: scode < 0 . + +zeit abgelaufen: scode = ack AND cd = myself. + +packet: + INT VAR snr, ant,err; + TASK VAR quelle, ziel; + snr := 0; + IF NOT zeichen da THEN routen erneuern FI; + REP + IF NOT zeichen da + THEN + forget (dr); + zeitueberwachung (snr, quelle, ziel, ant, dr); + ELIF NOT weiterleitung steht noch aus + THEN + packet eingang (snr, quelle, ziel, ant, dr); + FI; + IF snr = 1000 + THEN + packet weiterleiten + ELIF snr > 0 + THEN + IF ant > 6 AND erlaubt(station (quelle)) < 0 + THEN unerlaubt + ELSE + send (quelle,ziel,ant,dr,err); + fehlerbehandlung ; + FI + FI + UNTIL snr = 0 OR zeichen da PER. + +routen erneuern: + rzaehler DECR 1; + IF rzaehler = 0 + THEN + rzaehler := 20; + neue routen holen + FI. + +weiterleitung steht noch aus: merken <> 0. + +packet weiterleiten: + INT VAR reply; + IF NOT ((route.port (ant) AND 255) = channel OR route.port (ant) < 0) + THEN + send (netport (ant), out code, dr, reply); + IF reply = -2 + THEN + merken := ant; + DATASPACE VAR mds := dr + FI + ELSE + report ("Weiterleitung nicht möglich für "+text(ant)) + FI. + +fehlerbehandlung: + IF ok oder ziel nicht da THEN loesche verbindung (snr) FI. + +ok oder ziel nicht da: err=0 OR err=-1. + +netz info und steuerung: + IF scode = list code THEN list status + ELIF scode = erase code THEN strom beenden + ELIF scode = freigabe code AND stask = father THEN freigabelevel + ELIF scode >= route code THEN weitergaben + ELIF scode > tabellencode THEN routen ausliefern + ELSE forget (dr); ablehnen ("nicht möglich") + FI. + +weitergaben: + IF stask < father + THEN + IF scode = out code + THEN + BOUND INT VAR stx lng := dr; + INT VAR decoded lng := stx lng; + decode packet length (decoded lng); + transmit header (dr); + blockout (dr,1,drverwaltungslaenge,decoded lng); + transmit trailer + ELIF scode = route code + THEN + BOUND PARA VAR parah := dr; + PARA VAR para := parah; + pingpong (stask, ack, dr, reply); + neue sendung (para.quelle, para.ziel, para.sendecode, + para.zielstation, dr); + forget (dr); dr := nilspace; + send (stask, ack, dr) + FI + ELSE + forget (dr); + ablehnen ("nicht Sohn von "+name(father)) + FI. + +routen ausliefern: + neue sendung (stask, myself, -routen liefern code, scode-tabellencode,dr). + +freigabelevel: + BOUND STRUCT (INT stat,lvl) VAR lv := dr; + IF lv.stat > 0 AND lv.stat <= maxstat THEN erlaubt (lv.stat) := lv.lvl FI; + send (stask,ack,dr). + +unerlaubt: + report ("Fremdzugriff von "+text(station (quelle))+" auf "+nam(ziel) + +" code "+text(ant)); + loesche verbindung (snr); + forget (dr); dr := nilspace; + BOUND TEXT VAR errtxt := dr; + errtxt:="Kein Zugriff auf Station "+text (station (myself)); + neue sendung (ziel, quelle, error nak, station (quelle), dr). + +strom beenden: + BOUND TEXT VAR stromtext := dr; + INT VAR erase strom := int (stromtext); + forget (dr); + strom := erase strom; + IF falsche stromnummer THEN ablehnen ("Strom gibt es nicht") + ELSE + BOUND INFO VAR v := verbindung (strom); + IF + stask < supervisor OR stask = vx.quelle OR stask = vx.ziel + THEN + loeschen + ELSE ablehnen ("Nur Empfänger/Absender darf löschen") + FI + FI. + +loeschen: + IF sendeeintrag THEN + IF callee (vx.quelle) = vx.ziel THEN absender warnen FI; + loesche verbindung (strom) + ELSE + IF callee (vx.ziel) = vx.quelle THEN warnen FI; + loesche verbindung (strom) + FI; + dr := nilspace; + send (stask,ack,dr). + +absender warnen: + dr := nilspace; + send(vx.ziel,vx.quelle,1,dr,err) . + +warnen: + dr := nilspace; +errtxt := dr; errtxt:= "Station antwortet nicht"; +send (vx.quelle,vx.ziel,error nak, dr, err). + +falsche stromnummer: strom < 1 OR strom > max verbindungsnummer. +sendeeintrag: vx.quellrechner = station (myself). +vx: v.steuer. +END PROC communicate; + +PROC list option: + begin ("net list",PROC list net, sohn) +END PROC list option; + +PROC list net: + disable stop; + DATASPACE VAR ds ; + INT VAR scode; + REP + wait (ds, scode, stask); + forget (ds); ds := nilspace; + FILE VAR f := sequential file (output, ds); + list (f, father); + list netports; + IF is error THEN clear error; + forget(ds); + ds := nilspace; + f := sequential file (output, ds); + output (f); putline (f,errormessage); + clear error + FI; + send (stask, ack, ds) + PER. + +list netports: + INT VAR k; + FOR k FROM 1 UPTO 15 REP + TASK VAR tsk := task (k); + IF tsk < father + THEN + putline (f, name (tsk)); + list (f,tsk) + FI + PER. + +END PROC list net; + +PROC neue routen holen: + forget ("port intern", quiet); + fetch ("port intern"); + route := old ("port intern"); + neue routen +END PROC neue routen holen; + +PROC sendung untersuchen (TASK CONST q, z, INT CONST cod, DATASPACE VAR dr): + IF z = collector + THEN + verbindungsebene + ELIF station (z) <> 0 + THEN + sendung (q,z,cod,station (z),dr) + ELSE + ablehnen ("Station 0") + FI. + +verbindungsebene: + IF cod = 256 THEN name von fremdstation + ELIF cod > 256 + THEN + taskinfo fremd + ELIF callee (q) = z (* gegen errornak an collector *) + THEN + task id von fremd + FI. + +taskinfo fremd: sendung (q, collector, -task info code,cod-256,dr). + +task id von fremd: sendung (q, collector, -task id code, zielstation, dr) . + +name von fremdstation: + BOUND TASK VAR tsk := dr; + TASK VAR tsk1 := tsk; + forget (dr); + dr := nilspace; + sendung (q, tsk1, -name code, station (tsk1), dr). + +zielstation: cod. +END PROC sendung untersuchen; + +PROC sendung (TASK CONST q, z, INT CONST code, z stat, DATASPACE VAR dr): + IF z stat < 1 OR z stat > maxstat + THEN + ablehnen ("ungültige Stationsnummer"); + LEAVE sendung + FI; + INT VAR reply; + INT VAR rp := route.port (z stat) AND 255; + IF rp = 255 THEN neue routen holen ;rp := route.port (z stat) AND 255 FI; + IF rp = channel + THEN + sendung selbst betreiben + ELIF rp > 0 AND rp < 16 + THEN + sendung weitergeben + ELSE + ablehnen ("Station "+text(z stat)+" gibt es nicht") + FI. + +sendung selbst betreiben: + neue sendung (q, z, code, z stat, dr). + +sendung weitergeben: + DATASPACE VAR ds := nilspace; + BOUND PARA VAR p := ds; + p.quelle := q; + p.ziel := z; + p.zielstation := z stat; + p.sendecode := code; + call (netport (z stat), route code, ds, reply); + forget (ds); + pingpong (netport (z stat), 0, dr, reply); + forget (dr); + IF reply < 0 THEN ablehnen ("netport "+text(route.port(zstat)AND255) + + " fehlt") FI +END PROC sendung; + +PROC ablehnen (TEXT CONST t): + DATASPACE VAR vdr := nilspace; + BOUND TEXT VAR errtxt := vdr; + INT VAR err; + errtxt := t; + send (cd,stask, error nak, vdr,err); + forget (vdr). +END PROC ablehnen; + +PROC stop: + access catalogue; + IF exists task ("net timer") + THEN + TASK VAR nets := father (/"net timer"); + ELSE + nets := myself + FI; + nets := son (nets); + WHILE NOT (nets = niltask) REP + IF text (name (nets),3) = "net" OR name (nets) = "router" + THEN + end (nets) + FI; + nets := brother (nets) + PER +END PROC stop; + +PROC list status: + + DATASPACE VAR ds := nilspace; + FILE VAR f:=sequential file (output, ds); + line(f); + FOR strom FROM 1 UPTO max verbindungsnummer REP + IF strom > 0 THEN + BOUND INFO VAR v := verbindung (strom); + IF vx.strom <> 0 THEN info FI + FI; + PER; + send (stask, ack, ds). + +info: + put (f,"Strom "+text(strom)); + put (f,"(sqnr"+text(vx.sequenz)+"/"+text (v.maxseq)+")"); + IF sendeeintrag THEN sendeinfo ELSE empfangsinfo FI; + line (f). + +sendeeintrag: vx.quellrechner = station(myself) . + +sendeinfo: + IF v.typ = call im wait THEN put (f,"erwartet Antwort von") + ELIF v.typ = call in zustellung THEN put (f,"Ziel busy. Zielstation:") + ELIF v.typ = call im abbruch THEN put (f,"wird gelöscht bei Antwort von") + ELSE put (f,"sendet an") + FI; + put (f,vx.zielrechner); + put (f,". Absender ist """+nam (vx.quelle)+"""."). + +empfangsinfo: + IF v.typ = zustellung THEN + put (f,"Sendung noch nicht zustellbar") + ELSE + put (f,"empfängt von"); + put (f,vx.quellrechner); + FI; + put (f,". Empfaenger ist """+nam (vx.ziel)+"""."). + +vx: v.steuer. +END PROC list status; + +INT VAR quitmax := 3; + +ROW 15 TASK VAR net task; +ROW 15 INT VAR netz mode; + +PROC erlaube (INT CONST von, bis): + IF ein kanal gestartet + THEN + putline ("Warnung: 'erlaube' muß vor 'starte kanal'") + FI; + test (von); test (bis); + INT VAR i; + FOR i FROM von UPTO bis REP erlaubt (i) := 0 PER +END PROC erlaube; + +PROC sperre (INT CONST von, bis): + IF ein kanal gestartet + THEN + putline ("Warnung: 'sperre' muß vor 'starte kanal'") + FI; + test (von); test (bis); + INT VAR i; + FOR i FROM von UPTO bis REP erlaubt (i) :=-1 PER +END PROC sperre ; + +BOOL VAR alte routen, ein kanal gestartet; + +PROC definiere netz: + stop; + INT VAR i; + FOR i FROM 1 UPTO 15 REP net task (i) := niltask PER; + ein kanal gestartet := FALSE; + FILE VAR s := sequential file (output,"report"); + putline (s," N e u e r S t a r t " + date + " " + time of day ); + alte routen := exists ("port intern"); + IF alte routen + THEN + route := old ("port intern") + ELSE + route := new ("port intern"); + initialize routes + FI. + + initialize routes: + FOR i FROM 1 UPTO maxstat REP + route.zwischen(i) := i + PER. + +END PROC definiere netz; + +PROC starte kanal (INT CONST k,modus,stroeme): + ein kanal gestartet := TRUE; + IF exists (canal (k)) THEN end (canal (k)) FI; + IF stroeme <= 0 THEN errorstop ("3.Parameter negativ") FI; + quitmax := stroeme; + c := k; + IF c < 1 OR c > 15 THEN errorstop ("unzulässiger Kanal:"+text(c)) FI; + kanalmode := modus; + IF kanalmode < 1 OR kanalmode > max mode + THEN errorstop ("unzulässiger Netzbetriebsmodus:"+text(kanalmode)) + ELSE netz mode (c) := kanalmode + FI; + IF NOT exists task ("net port") + THEN + begin ("net port",PROC net io, net task (c)); + define collector (/"net port") + ELSE + begin ("net port "+text (c),PROC net io, net task (c)) + FI. +END PROC starte kanal; + +PROC routen (INT CONST von, bis, kanal, zw): + INT VAR i; + IF kanal < 0 OR kanal > 15 THEN errorstop ("Kanal unzulässig") FI; + test (von); test (bis); + FOR i FROM von UPTO bis REP + route.port (i) := kanal+256; + IF zw=0 + THEN + route.zwischen (i) := i + ELSE + test (zw); + route.zwischen (i) := zw + FI + PER. +END PROC routen; + +PROC routen (INT CONST von, bis, kanal): + routen (von, bis, kanal, 0) +END PROC routen; + +PROC test (INT CONST station): + IF station < 1 OR station > maxstat + THEN + errorstop (text (station) + " als Stationsnummer unzulässig") + FI +END PROC test; + +PROC aktiviere netz: +vorgegebene routen pruefen; +IF existstask ("net timer") THEN end (/"net timer") FI; +begin ("net timer",PROC timer,sohn); +IF NOT alte routen +THEN + routen aufbauen +ELSE + IF online THEN break FI +FI. + +vorgegebene routen pruefen: + INT VAR i; + FOR i FROM 1 UPTO maxstat REP + INT VAR s := route.port (i) AND 255; + IF s > 0 AND s <= 15 CAND nettask (s) = niltask + THEN + errorstop ("Kanal "+text(s)+" nicht gestartet, steht aber in Routen") + FI + PER. +END PROC aktiviere netz; + + +PROC routen aufbauen: + alte routen := TRUE; + c := channel; + break (quiet); + begin ("router", PROC rout0, sohn). +END PROC routen aufbauen; + +PROC rout0: + disable stop; + rout; + IF is error + THEN + put error + FI; + end (myself) +END PROC rout0; + +PROC rout: + IF c>0 THEN continue (c) FI; + clear error; enable stop; + fetch ("port intern"); + route := old ("port intern"); + routen aufbauen; + ds := old ("port intern"); + call (father, neue routen code, ds, reply). + +routen aufbauen: + access catalogue; + TASK VAR port := brother (myself); + WHILE NOT (port = niltask) REP + IF text (name (port),8) = "net port" THEN nachbarn FI; + port := brother (port) + PER; + IF online THEN putline ("Fertig. Weiter mit SV !") FI. + +aenderbar: route.port (st) < 256. + +nachbarn: + INT VAR st,reply; + FOR st FROM 1 UPTO maxstat REP + IF erlaubt (st) >= 0 AND st <> station (myself) AND aenderbar + THEN + IF online THEN put (name (port)); put (st) FI; + DATASPACE VAR ds := nilspace; + call (port, tabellencode+st, ds, reply); + IF reply = ack + THEN + BOUND STRUCT (ROW maxstat INT port, + ROW maxstat INT zwischen) VAR fremd := ds; + route.port (st) := channel(port); + route.zwischen (st) := st; + indirekte ziele + ELIF reply < 0 + THEN + errorstop ("netz läuft nicht (Kanalnummer falsch)") + ELSE + BOUND TEXT VAR xt := ds; + IF online THEN put (xt) FI; + FI; + IF online THEN line FI; + forget (ds) + FI + PER. + +indirekte ziele: + INT VAR kanal := fremd.port (station (myself)) AND 255; + INT VAR ind; + FOR ind FROM 1 UPTO maxstat REP + IF ind bei st bekannt AND NOT ((fremd.port (ind) AND 255) = kanal) + AND route.port (ind) < 256 + THEN + route.port (ind) := channel (port); + route.zwischen (ind) := st + FI + PER. + +ind bei st bekannt: NOT (fremd.port (ind) = -1). + +END PROC rout; + + +PROC timer: + disable stop; + access catalogue; + INT VAR old session := 1; + REP + IF session <> old session + THEN + define collector (/"net port"); + old session := session + FI; + clear error; + pause (30); + sende tick an alle ports + PER. + +sende tick an alle ports : + TASK VAR fb := son (father); + REP + IF NOT exists (fb) THEN access catalogue;LEAVE sende tick an alle portsFI; + IF channel (fb) > 0 + THEN + DATASPACE VAR ds := nilspace; + send (fb, ack, ds); + pause (10) + FI; + fb := brother (fb) + UNTIL fb = niltask PER. + +END PROC timer; + +PROC net io: + disable stop; + set net mode (kanalmode); + fetch ("port intern"); + route := old ("port intern"); + commanddialogue (FALSE); + continue (c); + communicate; + TEXT VAR emsg := "++++++ "+error message +" Zeile "+text(errorline); + clear error; + report (emsg); + end (myself) +END PROC net io; + +PROC start: run ("netz") END PROC start; + +END PACKET net manager; + diff --git a/system/net/1.8.7/src/net report b/system/net/1.8.7/src/net report new file mode 100644 index 0000000..ddc19d2 --- /dev/null +++ b/system/net/1.8.7/src/net report @@ -0,0 +1,41 @@ +PACKET net report DEFINES report, abgleich: +(* Version 3 (!) *) + +LET reportcode = 99, abgleichcode = 98; + +PROC abgleich (INT CONST ende, zwischen): + DATASPACE VAR ds := nilspace; + BOUND STRUCT (INT ende, zwischen) VAR x := ds; + x.ende := ende; + x.zwischen := zwischen; + call (father, abgleichcode, ds, rep); + INT VAR rep; + forget (ds) +END PROC abgleich; + +PROC report (TEXT CONST x): + report(x,"") +END PROC report; + +PROC report (TEXT CONST txt, info): + DATASPACE VAR net report := nilspace; + BOUND TEXT VAR rinfo := net report; + rinfo := date; + rinfo CAT " "+time of day +" "; + rinfo CAT name(myself)+":"; + rinfo CAT txt; + INT VAR i; + FOR i FROM 1 UPTO length (info) REP + INT VAR z := code (infoSUBi) ; + IF z < 32 OR z > 126 + THEN rinfo CAT "%"+text(z)+" " + ELSE rinfo CAT (infoSUBi)+" " + FI + PER; + call (father, report code , net report, reply); + INT VAR reply; + forget (net report); +END PROC report; + +END PACKET net report; + diff --git a/system/net/1.8.7/src/netz b/system/net/1.8.7/src/netz new file mode 100644 index 0000000..c237ba2 --- /dev/null +++ b/system/net/1.8.7/src/netz @@ -0,0 +1,20 @@ +IF exists ("port intern") THEN forget ("port intern") FI; +definiere netz; +list option; +erlaube(1,127); +sperre (1,9); +sperre (15,32); +sperre (37,37); +sperre (42,42); +sperre (46,47); +sperre (49,127); +routen (1, 32,8); +routen (33,43, 9); +routen (34,34,8); +routen (35,48,9); +starte kanal (9,11,10); +starte kanal (8,1,10); +aktiviere netz; + + + diff --git a/system/net/1.8.7/src/port server b/system/net/1.8.7/src/port server new file mode 100644 index 0000000..46c647f --- /dev/null +++ b/system/net/1.8.7/src/port server @@ -0,0 +1,164 @@ +PACKET port server: (* Autor : R. Ruland *) + (* Stand : 21.03.86 *) + +INT VAR port station; +TEXT VAR port := "PRINTER"; + +put ("gib Name des Zielspools : "); editget (port); line; +put ("gib Stationsnummer des Zielspools : "); get (port station); + +server channel (15); +spool duty ("Verwalter fuer Task """ + port + + """ auf Station " + text (port station)); + +LET max counter = 10 , + time slice = 300 , + + ack = 0 , + fetch code = 11 , + param fetch code = 21 , + file save code = 22 , + file type = 1003 , + + begin char = ""0"", + end char = ""1""; + + +INT VAR reply, old heap size; +TEXT VAR file name, write pass, read pass, sendername, buffer; +FILE VAR file; + +DATASPACE VAR ds, file ds, send ds; + +BOUND STRUCT (TEXT file name, write pass, read pass, sendername, INT station) VAR msg; +BOUND TEXT VAR error msg ; + +spool manager (PROC save file); + +PROC save file : + + disable stop ; + command dialogue (FALSE); + ds := nilspace; file ds := nilspace; send ds := nil space; + old heap size := heap size; + + REP + execute save file; + + IF is error THEN save error (error message) FI; + + IF heap size > old heap size + 4 + THEN collect heap garbage ; + old heap size := heap size + FI; + + PER + +ENDPROC save file; + + +PROC execute save file : + +enable stop; +forget (file ds) ; file ds := nilspace; +call (father, fetch code, file ds, reply); +IF reply <> ack + THEN error msg := ds; errorstop (error msg); + ELSE save file ds +FI; + +. save file ds : + IF type (file ds) = file type + THEN get file params; + insert file params; + call station (port station, port, file save code, file ds); + ELSE errorstop ("Datenraum hat falschen Typ") + FI; + +. get file params : + forget (ds); ds := nilspace; + call (father, param fetch code, ds, reply); + IF reply <> ack + THEN error msg := ds; errorstop (error msg); + ELSE msg := ds; + file name := msg. file name; + write pass := msg. write pass; + read pass := msg. read pass; + sendername := msg. sender name; + FI; + +. insert file params : + buffer := ""; + in headline (filename); + in headline (write pass); + in headline (read pass); + in headline (sendername); + file := sequential file (input, file ds) ; + headline (file, buffer); + +END PROC execute save file; + + +PROC call station (INT CONST order task station, TEXT CONST order task name, + INT CONST order code, DATASPACE VAR order ds) : + + INT VAR counter := 0; + TASK VAR order task; + disable stop; + REP order task := order task station // order task name; + IF is error CAND pos (error message, "antwortet nicht") > 0 + THEN clear error; + counter := min (max counter, counter + 1); + pause (counter * time slice); + ELSE enable stop; + forget (send ds); send ds := order ds; + call (order task, order code, send ds, reply); + disable stop; + IF reply = ack + THEN forget (order ds); order ds := send ds; + forget (send ds); + LEAVE call station + ELSE error msg := send ds; + errorstop (error msg); + FI; + FI; + PER; + +END PROC call station; + + +TASK OP // (INT CONST station, TEXT CONST name) : + + enable stop; + station / name + +END OP //; + + +PROC in headline (TEXT CONST information) : + IF pos (information, begin char) <> 0 + OR pos (information, end char) <> 0 + THEN errorstop ("Name darf nicht Code 0 oder Code 1 enthalten") FI; + buffer CAT begin char; + buffer CAT information; + buffer CAT end char; +END PROC in headline; + + +PROC save error (TEXT CONST message) : + clear error; + file name CAT "."; + file name CAT sender name; + file name CAT ".ERROR"; + file := sequential file (output, file name); + putline (file, " "); + putline (file, "Uebertragung nicht korrekt beendet "); + putline (file, " "); + put (file, "ERROR :"); put (file, message); + save (file name, public); + clear error; + forget(file name, quiet); +END PROC save error; + +ENDPACKET port server; + diff --git a/system/net/1.8.7/src/printer server b/system/net/1.8.7/src/printer server new file mode 100644 index 0000000..b1a30bc --- /dev/null +++ b/system/net/1.8.7/src/printer server @@ -0,0 +1,99 @@ +PACKET multi user printer : (* Autor : Rudolf Ruland *) + (* Stand : 24.03.86 *) + +INT VAR c; +put ("gib Druckerkanal : "); get (c); + + server channel (c); + station only (FALSE) ; + spool duty ("Ausgabe mit dem Drucker"); + spool control task (myself); + +LET ack = 0 , + + fetch code = 11 , + param fetch code = 21 , + file type = 1003 ; + +INT VAR reply, old heap size, sender station; +TEXT VAR file name, userid, password, sendername; +FILE VAR file ; + +DATASPACE VAR ds, file ds; + +BOUND STRUCT (TEXT file name, userid, password, sendername, INT station) VAR msg; +BOUND TEXT VAR error msg ; + +spool manager (PROC printer); + +PROC printer : + + disable stop ; + command dialogue (FALSE); + ds := nilspace; file ds := nilspace; + continue (server channel) ; + check error ("Kanal belegt"); + + old heap size := heap size ; + REP + execute print ; + + IF is error + THEN put error; + clear error; + FI ; + + IF heap size > old heap size + 4 + THEN collect heap garbage ; + old heap size := heap size + FI + PER + +ENDPROC printer ; + + +PROC execute print : + + enable stop ; + forget (file ds) ; file ds := nilspace ; + call (father, fetch code, file ds, reply) ; + IF reply = ack CAND type (file ds) = file type + THEN get file params; + print file + FI ; + +. get file params : + forget (ds); ds := nilspace; + call (father, param fetch code, ds, reply); + IF reply <> ack + THEN error msg := ds; errorstop (error msg); + ELSE msg := ds; + file name := msg. file name; + userid := msg. userid; + password := msg. password; + sendername := msg. sender name; + sender station := msg. station; + FI; + +. print file : + file := sequential file (input, file ds); + print (file, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + +ENDPROC execute print ; + + +PROC check error (TEXT CONST message) : + IF is error + THEN clear error; + rename myself (message); + IF is error THEN clear error; end (myself) FI; + pause (18000); + end (myself); + FI; +END PROC check error; + +ENDPACKET multi user printer ; + diff --git a/system/net/1.8.7/src/spool cmd b/system/net/1.8.7/src/spool cmd new file mode 100644 index 0000000..b44e799 --- /dev/null +++ b/system/net/1.8.7/src/spool cmd @@ -0,0 +1,112 @@ +PACKET spool cmd (* Autor: R. Ruland *) + (* Stand: 01.04.86 *) + DEFINES killer, + first, + start, + stop, + halt, + wait for halt : + +LET error nak = 2 , + + entry line code = 23 , + killer code = 24 , + first code = 25 , + start code = 26 , + stop code = 27 , + halt code = 28 , + wait for halt code = 29 ; + +DATASPACE VAR ds; + +BOUND STRUCT (TEXT entry line, INT index) VAR control msg; +BOUND TEXT VAR error msg ; + +INT VAR reply; + +INITFLAG VAR in this task := FALSE; + + +PROC control spool (TASK CONST spool, INT CONST control code, + TEXT CONST question, BOOL CONST leave) : + + enable stop; + initialize control msg; + WHILE valid spool entry + REP IF control question THEN control spool entry FI PER; + + . initialize control msg : + IF NOT initialized (in this task) THEN ds := nilspace FI; + forget (ds); ds := nilspace; control msg := ds; + control msg. entry line := ""; + control msg. index := 0; + say (""13""10""); + + . valid spool entry : + call (spool, entry line code, ds, reply); + IF reply = error nak + THEN error msg := ds; + errorstop (error msg); + FI; + control msg. index <> 0 + + . control question : + say (control msg. entry line); + yes (question) + + . control spool entry : + call (spool, control code, ds, reply); + IF reply = error nak + THEN error msg := ds; + errorstop (error msg); + FI; + IF leave THEN LEAVE control spool FI; + +END PROC control spool; + + +PROC killer (TASK CONST spool) : + + control spool (spool, killer code, " loeschen", FALSE) + +END PROC killer; + + +PROC first (TASK CONST spool) : + + control spool (spool, first code, " als erstes", TRUE) + +END PROC first; + + +PROC start (TASK CONST spool) : + + call (stop code, "", spool); + call (start code, "", spool); + +END PROC start; + + +PROC stop (TASK CONST spool) : + + call (stop code, "", spool); + +END PROC stop; + + +PROC halt (TASK CONST spool) : + + call (halt code, "", spool); + +END PROC halt; + + +PROC wait for halt (TASK CONST spool) : + + call (wait for halt code, "", spool); + +END PROC wait for halt; + + +END PACKET spool cmd; + diff --git a/system/net/1.8.7/src/spool manager b/system/net/1.8.7/src/spool manager new file mode 100644 index 0000000..e711ab4 --- /dev/null +++ b/system/net/1.8.7/src/spool manager @@ -0,0 +1,915 @@ +PACKET spool manager DEFINES (* Autor: J. Liedtke *) + (* R. Nolting *) + (* R. Ruland *) + (* Stand: 22.07.86 *) + + spool manager , + + server channel , + spool duty, + station only, + spool control task : + +LET que size = 101 , + + ack = 0 , + nak = 1 , + error nak = 2 , + message ack = 3 , + question ack = 4 , + second phase ack = 5 , + false code = 6 , + + fetch code = 11 , + save code = 12 , + exists code = 13 , + erase code = 14 , + list code = 15 , + all code = 17 , + param fetch code = 21 , + file save code = 22 , + entry line code = 23 , + killer code = 24 , + first code = 25 , + start code = 26 , + stop code = 27 , + halt code = 28 , + wait for halt code = 29 , + + continue code = 100 , + + file type = 1003 ; + +LET begin char = ""0"", + end char = ""1""; + +LET PARAMS = STRUCT (TEXT name, userid, password, sendername, INT station), + ENTRY = STRUCT (PARAMS ds params, TEXT entry line, DATASPACE space); + +ROW que size ENTRY VAR que ; + +PARAMS CONST empty params := PARAMS : ("", "", "", "", -1); + +PARAMS VAR save params, file save params; + +ENTRY VAR fetch entry; + +FILE VAR file; + +INT VAR order, last order, phase, reply, old heap size, first, last, list index, + begin pos, end pos, order task station, sp channel, counter; + +TEXT VAR order task name, buffer, sp duty, start time; + +BOOL VAR server is waiting, stop command pending, stat only, valid fetch entry; + +TASK VAR order task, last order task, server, calling parent, task in control; + +INITFLAG VAR in this task := FALSE; + +DATASPACE VAR ds; + +BOUND STRUCT (TEXT name, userid, password) VAR msg; +BOUND STRUCT (TEXT entry line, INT index) VAR control msg; +BOUND PARAMS VAR fetch msg; +BOUND THESAURUS VAR all msg; +BOUND TEXT VAR error msg ; + + +. first entry : que (first) +. list entry : que (list index) +. last entry : que (last) + +. que is empty : first = last +. que is full : first = next (last) +.; + +sp channel := 0; +sp duty := ""; +stat only := FALSE; +task in control := myself; + +PROC server channel (INT CONST channel nr) : + IF channel nr <= 0 OR channel nr >= 33 + THEN errorstop ("falsche Kanalangabe") FI; + sp channel := channel nr; +END PROC server channel; + +INT PROC server channel : + sp channel +END PROC server channel; + + +PROC station only (BOOL CONST flag) : + stat only := flag +END PROC station only; + +BOOL PROC station only : + stat only +END PROC station only; + + +PROC spool duty (TEXT CONST duty) : + sp duty := duty; +END PROC spool duty; + +TEXT PROC spool duty : + sp duty +END PROC spool duty; + + +PROC spool control task (TASK CONST task id): + task in control := task id; +END PROC spool control task; + +TASK PROC spool control task : + task in control +END PROC spool control task; + + +PROC spool manager (PROC server start) : + + spool manager (PROC server start, TRUE) + +END PROC spool manager; + + +PROC spool manager (PROC server start, BOOL CONST with start) : + + set autonom ; + break ; + disable stop ; + initialize spool manager ; + REP forget (ds) ; + wait (ds, order, order task) ; + IF order <> second phase ack + THEN prepare first phase ; + spool (PROC server start); + ELIF order task = last order task + THEN prepare second phase ; + spool (PROC server start); + ELSE send nak + FI ; + send error if necessary ; + collect heap garbage if necessary + PER + + . initialize spool manager : + initialize if necessary; + stop; + erase fetch entry; + IF with start THEN start (PROC server start) FI; + + . initialize if necessary : + IF NOT initialized (in this task) + THEN FOR list index FROM 1 UPTO que size + REP list entry. space := nilspace PER; + fetch entry. space := nilspace; + ds := nilspace; + last order task := niltask; + server := niltask; + calling parent := niltask; + server is waiting := FALSE; + stop command pending := FALSE; + old heap size := 0; + clear spool; + FI; + + . prepare first phase : + IF order = save code OR order = erase code OR order = stop code + THEN phase := 1 ; + last order := order ; + last order task := order task ; + FI; + + . prepare second phase : + phase INCR 1 ; + order := last order + + . send nak : + forget (ds) ; + ds := nilspace ; + send (order task, nak, ds); + + . send error if necessary : + IF is error + THEN forget (ds) ; + ds := nilspace ; + error msg := ds ; + CONCR (error msg) := error message; + clear error; + send (order task, error nak, ds) + FI; + + . collect heap garbage if necessary : + IF heap size > old heap size + 2 + THEN collect heap garbage; + old heap size := heap size; + FI; + +END PROC spool manager; + + +PROC spool (PROC server start): + + command dialogue (FALSE); + enable stop; + IF station only CAND station (ordertask) <> station (myself) + THEN errorstop ("kein Zugriffsrecht auf Task " + text (station(myself)) + + "/""" + name(myself) + """") + FI; + + SELECT order OF + + CASE fetch code : out of que + CASE param fetch code : send fetch params + CASE save code : new que entry + CASE file save code : new file que entry + CASE exists code : exists que entry + CASE erase code : erase que entry + CASE list code : send spool list + CASE all code : send owners ds names + + OTHERWISE : + + IF order >= continue code AND order task = supervisor + THEN forget (ds); + spool command (PROC server start) + + ELIF spool control allowed by order task + THEN SELECT order OF + CASE entry line code : send next entry line + CASE killer code : kill entry + CASE first code : make to first + CASE start code : start server + CASE stop code : stop server + CASE halt code : halt server + CASE wait for halt code : wait for halt + OTHERWISE : errorstop ("falscher Auftrag fuer Task """ + + name(myself) + """") + END SELECT + + ELSE errorstop ("falscher Auftrag fuer Task """ + + name(myself) + """") + FI; + END SELECT; + + +. spool control allowed by order task : + (order task = spool control task OR order task < spool control task + OR spool control task = supervisor) + AND station (order task) = station (myself) +. + out of que : + IF NOT (order task = server) + THEN errorstop ("keine Servertask") + ELIF stop command pending + THEN forget (ds); + stop; + erase fetch entry; + ELIF que is empty + THEN forget (ds) ; + erase fetch entry; + server is waiting := TRUE; + ELSE send first entry; + FI; + +. + send fetch params : + IF order task = server + THEN send params + ELSE errorstop ("keine Servertask") + FI; + + . send params : + forget(ds); ds := nilspace; fetch msg := ds; + fetch msg := fetch entry. ds params; + send (order task, ack, ds); + +. + new que entry : + IF phase = 1 + THEN prepare into que + ELSE into que + FI; + +. + prepare into que : + msg := ds ; + save params. name := msg.name; + save params. userid := msg.userid; + save params. password := msg.password; + save params. sendername := name (order task); + save params. station := station (order task); + forget (ds); ds := nilspace; + send (order task, second phase ack, ds); + +. + new file que entry : + IF type (ds) <> file type + THEN errorstop ("Datenraum hat falschen Typ"); + ELSE get file params; + into que; + FI; + + . get file params : + file := sequential file (input, ds); + end pos := 0; + next headline information (file save params. name); + next headline information (file save params. userid); + next headline information (file save params. password); + next headline information (file save params. sendername); + next headline information (buffer); + file save params. station := int (buffer); + IF NOT last conversion ok + THEN file save params. station := station (order task) FI; + IF file save params. sendername = "" + THEN file save params. sendername := name (order task) FI; + IF file save params. name = "" + THEN IF headline (file) <> "" + THEN file save params. name := headline (file); + ELSE errorstop ("Name unzulaessig") + FI; + ELSE headline (file, file save params. name); + FI; + +. + exists que entry : + msg := ds ; + order task name := name (order task); + order task station := station (order task); + to first que entry; + WHILE next que entry found + REP IF is entry from order task (msg. name) + THEN send ack; + LEAVE exists que entry + FI; + PER ; + forget (ds); ds := nilspace; + send (order task, false code, ds) + +. + erase que entry : + msg := ds ; + order task name := name (order task); + order task station := station (order task); + IF phase = 1 + THEN ask for erase + ELSE erase entry from order task + FI; + + . ask for erase : + to first que entry; + WHILE next que entry found + REP IF is entry from order task (msg. name) + THEN manager question ("""" + msg.name + """ loeschen"); + LEAVE erase que entry + FI; + PER ; + manager message ("""" + msg.name + """ existiert nicht"); + + . erase entry from order task : + IF is entry from order task (msg. name) + THEN delete que entry; + LEAVE erase que entry + ELSE to first que entry; + WHILE next que entry found + REP IF is entry from order task (msg. name) + THEN delete que entry; + LEAVE erase que entry + FI ; + PER ; + manager message ("""" + msg.name + """ existiert nicht"); + FI; + + . delete que entry : + erase entry (list index) ; + send ack; + +. + send owners ds names: + order task name := name (order task); + order task station := station (order task); + forget (ds); ds := nilspace; all msg := ds; + all msg := empty thesaurus; + to first que entry; + WHILE next que entry found + REP IF is entry from order task ("") + THEN insert (all msg, list entry. ds params. name) + FI; + PER; + send (order task, ack, ds) + +. + send spool list : + list spool; + send (order task, ack, ds); + +. + send next entry line : + control msg := ds; + get next entry line (control msg. entry line, control msg. index); + send (order task, ack, ds); + +. + kill entry : + control msg := ds; + list index := control msg. index; + IF is valid que entry (list index) + THEN erase entry (list index) + FI; + send (order task, ack, ds); + +. + make to first : + control msg := ds; + list index := control msg. index; + IF is valid que entry (list index) + THEN new first (list entry); + erase entry (list index); + FI; + send (order task, ack, ds); + +. + start server : + IF exists (server) THEN errorstop ("Spool muß zuerst gestoppt werden") FI; + start (PROC server start); + IF server channel <= 0 OR server channel >= 33 + THEN manager message ("WARNUNG : Serverkanal nicht eingestellt"); + ELSE send ack + FI; + +. + stop server: + IF phase = 1 + THEN stop; + IF valid fetch entry + THEN valid fetch entry := FALSE; + manager question (""13""10"" + + fetch entry. entry line + " neu eintragen"); + ELSE erase fetch entry; + send ack; + FI; + ELSE IF fetch entry. entry line <> "" THEN new first (fetch entry) FI; + erase fetch entry; + send ack; + FI; + +. + halt server : + stop command pending := TRUE; + IF NOT exists (server) OR server is waiting + THEN stop; + erase fetch entry; + FI; + send ack; + +. + wait for halt : + IF exists (calling parent) + THEN errorstop ("Task """ + name (calling parent) + """ wartet schon auf halt") + ELSE calling parent := order task; + stop command pending := TRUE; + forget (ds); + IF NOT exists (server) OR server is waiting + THEN stop; + erase fetch entry; + FI; + FI; + +END PROC spool; + + +PROC send first entry : + + forget (ds); ds := first entry. space; + send (server, ack, ds, reply) ; + IF reply = ack + THEN server is waiting := FALSE; + start time := time of day; + start time CAT " am "; + start time CAT date; + erase fetch entry; + fetch entry := first entry; + erase entry (first); + valid fetch entry := TRUE; + ELSE forget (ds); + FI; + +END PROC send first entry; + + +PROC into que : + + IF que is full + THEN errorstop ("Spool ist voll") + ELSE make new entry; + send ack; + awake server if necessary + FI; + + . make new entry : + IF order = save code + THEN last entry. ds params := save params; + save params := empty params; + ELSE last entry. ds params := file save params; + file save params := empty params; + FI; + last entry. space := ds; + counter INCR 1; + build entry line; + last := next (last) ; + + . build entry line : + IF LENGTH last entry. ds params. sender name > 16 + THEN buffer := subtext (last entry. ds params. sender name, 1, 13); + buffer CAT "..."""; + ELSE buffer := last entry. ds params. sender name; + buffer CAT """"; + buffer := text (buffer, 17); + FI; + last entry. entry line := entry station text; + last entry. entry line CAT "/"""; + last entry. entry line CAT buffer; + last entry. entry line CAT " : """ ; + last entry. entry line CAT last entry. ds params. name; + last entry. entry line CAT """ (" ; + last entry. entry line CAT text (storage (last entry. space)); + last entry. entry line CAT " K)"; + + . entry station text : + IF last entry. ds params. station = 0 + THEN " " + ELSE text (last entry. ds params. station, 3) + FI + + . awake server if necessary : + IF server is waiting THEN send first entry FI; + +END PROC into que; + + +PROC list spool : + + forget (ds); ds := nilspace; + file := sequential file (output, ds) ; + max line length (file, 1000); + headline(file, station text + "/""" + name (myself) + """"); + put spool duty; + put current job; + put spool que; + + . station text : + IF station(myself) = 0 + THEN "" + ELSE text (station(myself)) + FI + + . put spool duty : + IF spool duty <> "" + THEN write (file, "Aufgabe: "); + write (file, spool duty ); + line (file, 2); + FI; + + . put current job : + IF valid fetch entry AND exists (server) + THEN write (file, "In Bearbeitung seit "); + write (file, start time); + write (file, ":"); + line (file, 2); + putline (file, fetch entry. entry line); + IF stop command pending + THEN putline (file, "Spool wird nach diesem Auftrag deaktiviert"); + FI; + line (file); + ELSE write (file, "kein Auftrag in Bearbeitung"); + IF NOT exists (server) + THEN write (file, ", da Spool deaktiviert"); + ELIF que is empty + THEN write (file, ", da Warteschlange leer"); + LEAVE list spool; + FI; + line (file, 2); + FI; + + . put spool que : + IF que is empty + THEN putline (file, "Warteschlange ist leer"); + ELSE write (file, "Warteschlange ("); + write (file, text (counter)); + write (file, " Auftraege):"); + line (file, 2); + to first que entry ; + WHILE next que entry found + REP putline (file, list entry. entry line) PER; + FI; + +END PROC list spool ; + + +PROC clear spool : + + first := 1; + last := 1; + counter := 0; + FOR list index FROM 1 UPTO que size + REP list entry. ds params := empty params; + list entry. entry line := ""; + forget (list entry. space) + PER; + +END PROC clear spool; + +(*********************************************************************) +(* Hilfsprozeduren zum Spoolmanager *) + +BOOL PROC is valid que entry (INT CONST index) : + + que (index). entry line <> "" + +END PROC is valid que entry; + + +INT PROC next (INT CONST index) : + + IF index < que size + THEN index + 1 + ELSE 1 + FI + +END PROC next; + + +PROC to first que entry : + + list index := first - 1; + +ENDPROC to first que entry ; + + +BOOL PROC next que entry found : + + list index := next (list index); + WHILE is not last que entry + REP IF is valid que entry (list index) + THEN LEAVE next que entry found WITH TRUE FI; + list index := next (list index); + PER; + FALSE + + . is not last que entry : + list index <> last + +ENDPROC next que entry found ; + + +PROC get next entry line (TEXT VAR entry line, INT VAR index) : + + IF index = 0 + THEN list index := first - 1 + ELSE list index := index + FI; + IF next que entry found + THEN entry line := list entry. entry line; + index := list index; + ELSE entry line := ""; + index := 0; + FI; + +END PROC get next entry line; + + +PROC new first (ENTRY VAR new first entry) : + + IF que is full + THEN errorstop ("Spool ist voll") + ELSE first DECR 1 ; + IF first = 0 THEN first := que size FI; + first entry := new first entry; + counter INCR 1; + FI; + +END PROC new first; + + +PROC erase entry (INT CONST index) : + + entry. ds params := empty params; + entry. entry line := ""; + forget (entry.space) ; + counter DECR 1; + IF index = first + THEN inc first + FI ; + + . entry : que (index) + + . inc first : + REP first := next (first) + UNTIL que is empty OR is valid que entry (first) PER + +END PROC erase entry; + + +PROC erase fetch entry : + + fetch entry. ds params := empty params; + fetch entry. entry line := ""; + forget (fetch entry. space); + valid fetch entry := FALSE; + +END PROC erase fetch entry; + + +BOOL PROC is entry from order task (TEXT CONST file name) : + + correct order task CAND correct filename + + . correct order task : + order task name = list entry. ds params. sendername + AND order task station = list entry. ds params. station + + . correct file name : + file name = "" OR file name = list entry. ds params. name + +END PROC is entry from order task; + + +PROC start (PROC server start): + + begin (PROC server start, server); + +END PROC start; + + +PROC stop : + + stop server; + send calling parent reply if necessary; + + . stop server: + IF exists (server) THEN end (server) FI; + server := niltask; + server is waiting := FALSE; + stop command pending := FALSE; + + . send calling parent reply if necessary : + IF exists (calling parent) + THEN forget (ds); ds := nilspace; + send (calling parent, ack, ds); + calling parent := niltask; + FI; + +END PROC stop; + + +PROC next headline information (TEXT VAR t): + + begin pos := pos (headline (file), begin char, end pos + 1); + IF begin pos = 0 + THEN begin pos := LENGTH headline (file) + 1; + t := ""; + ELSE end pos := pos (headline (file), end char, begin pos + 1); + IF end pos = 0 + THEN end pos := LENGTH headline (file) + 1; + t := ""; + ELSE t := subtext (headline (file), begin pos+1, end pos-1) + FI + FI + +END PROC next headline information; + + +PROC send ack : + + forget (ds); ds := nilspace; + send (order task, ack, ds) + +END PROC send ack; + + +PROC manager question (TEXT CONST question) : + + forget (ds); ds := nilspace; error msg := ds ; + error msg := question ; + send (order task, question ack, ds) + +ENDPROC manager question ; + + +PROC manager message (TEXT CONST message) : + + forget (ds); ds := nilspace; error msg := ds ; + error msg := message ; + send (order task, message ack, ds) + +ENDPROC manager message ; + +(*********************************************************************) +(* Spool - Kommandos *) + +INT VAR command index , params ; +TEXT VAR command line, param 1, param 2 ; + +LET spool command list = +"break:1.0start:2.01stop:4.0halt:5.0first:6.0killer:7.0listspool:8.0 +clearspool:9.0spoolcontrolby:10.1"; + +PROC spool command (PROC server start) : + + enable stop ; + continue (order - continue code) ; + disable stop ; + REP command dialogue (TRUE) ; + get command ("gib Spool-Kommando:", command line); + analyze command (spool command list, command line, 3, command index, + params, param1, param2); + execute command (PROC server start); + UNTIL NOT online PER; + command dialogue (FALSE); + break (quiet); + set autonom; + +END PROC spool command; + + +PROC execute command (PROC server start) : + + enable stop; + SELECT command index OF + CASE 1 : break + CASE 2 : start server + CASE 3 : start server with new channel + CASE 4 : stop server + CASE 5 : halt server + CASE 6 : first cmd + CASE 7 : killer cmd + CASE 8 : show spool list + CASE 9 : clear spool + CASE 10 : spool control task (task (param1)) + OTHERWISE do (command line) + END SELECT; + + . start server : + IF server channel <= 0 OR server channel >= 33 + THEN line; + putline ("WARNUNG : Serverkanal nicht eingestellt"); + FI; + stop server; + start (PROC server start); + + . start server with new channel: + INT VAR i := int (param1); + IF last conversion ok + THEN server channel (i); + start server; + ELSE errorstop ("falsche Kanalangabe") + FI; + + . stop server : + disable stop; + stop; + IF valid fetch entry CAND + yes (""13""10"" + fetch entry. entry line + " neu eintragen") + THEN new first (fetch entry) FI; + erase fetch entry; + enable stop; + + . halt server : + stop command pending := TRUE; + IF NOT exists (server) OR server is waiting + THEN stop server; + erase fetch entry; + FI; + + . first cmd : + line ; + to first que entry ; + WHILE next que entry found + REP say (list entry. entry line) ; + IF yes (" als erstes") + THEN new first (list entry); + erase entry (list index); + LEAVE first cmd + FI ; + PER; + + . killer cmd : + line ; + to first que entry ; + WHILE next que entry found + REP say (list entry. entry line) ; + IF yes (" loeschen") THEN erase entry (list index) FI ; + PER; + + . show spool list : + list spool; + disable stop; + show (file); + forget (ds); + +ENDPROC execute command ; + +ENDPACKET spool manager; + diff --git a/system/net/unknown/doc/EUMEL Netz b/system/net/unknown/doc/EUMEL Netz new file mode 100644 index 0000000..941e2ea --- /dev/null +++ b/system/net/unknown/doc/EUMEL Netz @@ -0,0 +1,829 @@ +#type ("trium8")##limit (11.0)# +#start(2.5,1.5)##pagelength (17.4)# +#block# +#headeven# + +% EUMEL-Netzbeschreibung + + +#end# +#headodd# + +#center#Inhalt#right#% + + +#end# + +#type ("triumb12")# +1. Einleitung + + +Teil 1: Netz einrichten und benutzen +#type ("trium8")# + +1. Benutzung des Netzes + +2. Hardwarevoraussetzungen + +3. Einrichten des Netzes + +4. Informationsmöglichkeiten + +5. Eingriffsmöglichkeiten + +6. Fehlerbehebung im Netz + +#type ("triumb12")# + +Teil 2: Arbeitsweise der Netzsoftware +#type ("trium8")# + +1. Die Netztask + +2. Protokollebenen + +3. Stand der Netzsoftware + +#page# +#headodd# + +#center#Einleitung#right#% + + +#end# + +#type("triumb12")# +1. Einleitung #type("trium8")# + + +Das EUMEL-Netz dient dazu mehrere EUMEL-Rechner (sog. Stationen) mit­ +einander zu koppeln. Diese Kopplung wird von Betriebsystem dazu benutzt, das +Sendungskonzept (siehe Systemhandbuch 1.7, Intertaskkommunikation) so auszu­ +dehnen, daß Tasks verschiedener Stationen einander Datenräume zusenden +können. Auf dem Sendungskonzept aufbauende Konzepte nutzen daher automa­ +tisch das Netz aus: So ist es z.B. möglich + +- von einer Station aus auf einer anderen zu Drucken, + +- in PUBLIC einer anderen Station Dateien zu sichern (save), vorausgesetzt, daß + PUBLIC dort ein free global manager ist, + +- auf einer anderen Station zu archivieren (z.B. wenn das eigene Archivlaufwerk + defekt ist oder ein anderes Format hat). + +Das Netz kann ab EUMEL-Version 1.7.3 eingesetzt werden. + + +#type("triumb12")# +Teil 1: Netz einrichten und benutzen + +1. Benutzung des Netzes #type("trium8")# +#headodd# + +#center#Teil 1: Netz einrichten und benutzen#right#% + + +#end# + + Zur Benutzung des Netzes stehen folgende Operatoren und Prozeduren zur + Verfügung: + + +1.1 + + TASK OP / (INT CONST station, TEXT CONST taskname) + + liefert die Task #on("bold")#taskname#off("bold")# von der Station #on("bold")#station#off("bold")#. + + Wenn die Station #on("bold")#station#off("bold")# nicht am Netz ist oder nicht eingeschaltet ist, wird + solange gewartet, bis das der Fall ist. + + Fehlerfälle: + + - task "..." gibt es nicht + + Die angeforderte Task gibt es in der Zielstation nicht. + + - Collectortask fehlt + + Das Kommando #on("bold")#define collector#off("bold")# wurde nicht gegeben (siehe 4.2). + + - Station x antwortet nicht + + Eine nicht vorhandene oder abgeschaltete Station wurde angesprochen. + Hinweis: Dieser Fehler wird angenommen, wenn eine Überwachungszeit + von ca. 30 Sekunden verschrichen ist, ohne daß Station x die + Taskidentifikation angeliefert hat. + + Beispiel: + + list (5/"PUBLIC") + + Dateiliste von PUBLIC auf Station 5 wird angefordert. + +1.2 + + TASK OP / (INT CONST station, TASK CONST task) + + liefert + + station / name (task) . + + + Beispiel: + + list (4/archive) + + +1.3 + + INT PROC station (TASK CONST task) + + liefert die Stationsnummer der Task #on("bold")#task#off("bold")#. + + Beispiel: + + put (station (myself)) + + gibt die eigene Stationsnummer aus. + + +1.4 + + PROC archive (TEXT CONST archivename, INT CONST station) + + dient dazu das Archiv auf der Station #on("bold")#station#off("bold")# anzumelden. + + Beispiel: + + archive ("std", 4); list (4/archive) + + gibt das Inhaltsverzeichnis der Archivfloppy im Laufwerk der Station 4 aus. + Hinweis: Vergessen Sie bei solchen Querarchivierungen nicht die Stations­ + angabe bei jedem einzelnen Archivkommando (z.B fetch ("xxx", #on("bold")#4/#off("bold")# + archive). + Hinweis: Querarchivieren ist langsam. Verwenden Sie es nur, wenn Sie Flop­ + pyformate umsetzen wollen. + + +1.5 + + PROC free global manager + + dient dazu, die eigene Task über das Netz ansprechbar zu machen. Jede + andere Task im Netz kann dann die üblichen Manageraufrufe ('save', 'fetch', + u.s.w.) an die eigene Task machen, sofern diese nicht an ein Terminal gekop­ + pelt ist. + + Die Task wird (wie bei 'break') abgekoppelt und meldet sich in Zukunft mit + 'maintenance' statt mit 'gib kommando'. + + Beispiel: + + An Station 4 ruft man in der Task 'hugo' das Kommando #on("bold")#free global manager#off("bold")# + auf. Anschließend kann man von jeder Station aus z.B. 'list (4/"hugo")' u.s.w. + machen. + + +1.6 + + TEXT PROC name (TASK CONST t) + + Diese (schon immer vorhandene) Prozedur wurde dahingehend erweitert, daß der + Name einer Task einer anderen Station über Netz angefordert wird. + + Fehlerfall: + + Station x antwortet nicht + + + + +#type("triumb12")#2. Hardwarevoraussetzungen#type("trium8")# + +2.1 Zwei Stationen + + Sie können zwei Stationen miteinander Vernetzen, wenn Sie dafür an jeder + Station eine V24-Schnittstelle zur Verfügung stellen. + + Diese beiden Schnittstellen verbinden Sie mit einem Kabel zur Rechner­ + kopplung (siehe Systemhandbuch 1.7 Teil 2). + +2.2 Mehrere Stationen + + Wenn Sie mehr als zwei Stationen vernetzen wollen, brauchen neben je + einer V24 an jeder Station noch je eine Netzanschlußbox. + + Jede Box besitzt eine V24-Schnittstelle zum Anschluß an die V24- + Schnittstelle der zugeorneten Station und eine weitere Schnittstelle zur + Verbindung der Boxen untereinander. + + +#type("triumb12")#3. Einrichten des Netzes #type("trium8")# + +Hinweis: Dieses Kapitel ist nur für Systembetreuer wichtig. + +3.1 Legen Sie Stationsnummern für die am Netz beteiligten Rechner fest (von 1 an + aufsteigend). + + Die Boxen haben ebenfalls Stationsnummern. Die Stationsnummern der Box + und des zugeordneten Rechners müssen übereinstimmen. + + +3.2 Holen Sie an jeder Station die Task #on("bold")#configurator#off("bold")# an ein Terminal und geben Sie + das Kommando #on("bold")#define collector ("net port")#off("bold")#. Geben Sie außerdem das + Kommando #on("bold")#define station (x)#off("bold")#, wobei #on("bold")#x#off("bold")# die gewählte Stationsnummer ist. + + Hinweis: Taskkommunikationen, die zu dem Zeitpunkt laufen, führen zu feh­ + lerhaften Verhalten. Dies liegt daran, daß durch #on("bold")#define station#off("bold")# alle + Task-Id's geändert werden müssen, weil eine Task-Id u.a. die + Stationsnummer der eigenen Station enthält (siehe 2.3). TASK- + Variable, die noch Task-Id's mit keiner oder falscher Stationsnum­ + mer enthalten, können nicht mehr zum Ansprechen einer Task + verwendet werden. + + Beispiel: Der Spoolmanager (siehe Benutzerhandbuch 1.7 Teil 12) richtet + beim Kommando #on("bold")#start#off("bold")# einen Worker ein und merkt sich dessen + Task-Id in einer TASK-Variablen, um sicherzustellen, daß nur der + Worker Dateien zum Drucken abholt. Wird jetzt das Kommando #on("bold")# + define station#off("bold")# gegeben, kann der Spoolmanager seinen Worker + nicht mehr identifizieren, weil der Worker eine neue Task-Id er­ + halten hat. Man muß daher den Worker löschen und mit dem + Kommando #on("bold")#start#off("bold")# im Spoolmanager wieder neu einrichten. + + + Sinnvollerweise gibt man #on("bold")#define station#off("bold")# sofort nach den Laden eines + frischen Systems von Archiv. + + Konfigurieren Sie mit dem Kommando #on("bold")#configurate#off("bold")# den für das Netz vorgese­ + henen Kanal auf + + - transparent + - 9600 Baud (Standardeinstellung der Boxen) + - RTS/CTS-Protokoll + - großen Puffer + - 8 bit + - even parity + - 1 stopbit. + + Falls diese Einstellungen nicht alle angeboten werden, klären Sie mit Ihrem + Rechnerlieferanten, ob und wie diese Einstellungen erreicht werden können. + Hinweis: Notfalls kann auf das RTS/CTS-Protokoll verzichtet werden, wenn + der Eingabepuffer der Station groß genug ist. Die Anzahl simultan + laufender Netzkommunikationen ist dann auf + + puffergröße DIV 150 + + begrenzt (bei Z80, 8086: 3; bei M20: 10). + Hinweis: Es können auch andere Baudraten (2400, 4800, 19200) an der Box + eingestellt werden. + +3.3 Achten Sie bei der Verbindung von der Station zur Netzbox (bzw. zur Gegen­ + station bei einem Zweistationennetz ohne Boxen) darauf, daß neben den + Empfangs- und Sendeleitungen auch die Leitungen RTS und CTS verdrahtet + werden, also ein 5 poliges Kabel verwendet wird (siehe Systemhandbuch 1.7 + Teil 2). Die Pin-Belegung der Boxen entspricht den dortigen Angaben. + + Beispiel: + + Verbindung eines CSK-Systems mit der Box: + + Stecker Stecker + Pin Pin + + 2 <---------> 3 + 3 <---------> 2 + 4 <---------> 5 + 5 <---------> 4 + 7 <---------> 7 + + +3.4 Richten Sie eine Task #on("bold")#net#off("bold")# unter #on("bold")#SYSUR#off("bold")# ein und insertieren Sie dort die Datei­ +en + + net report/M + basic net + net manager/M. + + Beantworten Sie die Frage nach dem Kanal für das Netz und nach der Fluß­ + kontrolle (RTS/CTS). + + +#type("triumb12")#4. Informationsmöglichkeiten #type("trium8")# + + In der Task #on("bold")#net#off("bold")# wird eine Datei #on("bold")#report#off("bold")# geführt in der Fehlersituationen des + Netzes verzeichnet werden. Diese Datei kann in jeder anderen Task mit #on("bold")#list + (/"net")#off("bold")# angezeigt werden. + + In jeder Task kann durch das Kommando #on("bold")#list (/"net port")#off("bold")# eine Übersicht über + die momentan laufenden Netzübertragungen der eigenen Station erhalten + werden. + + +#type("triumb12")#5. Eingriffsmöglichkeiten #type("trium8")# +#headodd# + +#center#Eingriffsmöglichkeiten#right#% + + +#end# + +5.1 Jede Task kann Sende- und Empfangsströme, die bei #on("bold")#list (/"net port")#off("bold")# gemel­ + det worden sind und die eigene Task betreffen, abbrechen. Hierzu ist das + Kommando #on("bold")#erase ("x",/"net port")#off ("bold")# zu geben, wobei x die Stromnummer (aus + dem 'list') ist. + + Unberechtigte Löschversuche werden abgewiesen. + + Von der Task 'net' aus können jedoch damit beliebige Ströme abgebrochen + werden. + +5.2 Durch das Kommando #on("bold")#start#off("bold")# kann von der Task 'net' aus das Netz neu gestartet + werden. Dabei werden alle augenblicklichen Netzkommunikationen gelöscht. + Die Tasks 'net port' und 'net timer' werden dabei gelöscht und neu eingerich­ + tet. + + #on("bold")#start (kanal, quit)#off("bold")# wirkt wie #on("bold")#start#off("bold")#. Zustzlich wird als Netzkanal 'kanal' eingestellt + und maximal 'quit' Empfangsströme zugelassen. 'quit' ist auf 3 zu setzen, + wenn der Kanal ohne RTS/CTS angeschlossen ist (siehe 3.2). + + +#type("triumb12")#6. Fehlersuche im Netz #type("trium8")# + + Fehler im Netz können sich verschiedenartig auswirken. Im Folgenden wird auf + einige Beispiele eingegangen: + + Beispiel: + + Auf #on("bold")#list (4/public)#off("bold")# erfolgt die Meldung 'Station 4 antwortet nicht'. + + Fehlermöglichkeiten: + + - Station 4 gibt es nicht am Netz. + Abhilfe: Richtige Station angeben. + + - Station 4 ist nicht eingeschaltet. + Abhilfe: Station 4 einschalten. Kommando erneut geben. + + - Netztask an Station 4 ist nicht arbeitsfähig. + Abhilfe: Kommando 'start' in der Task 'net'. + + - Stationsnummern und Boxnummern stimmen nicht überein. + Abhilfe: Mit 'define station' Stationsnummern korrigieren (siehe 3.2). + + - Verbindung Rechner/Box am eigenen Rechner oder an Station 4 fehlt. + Abhilfe: Verbindungen überprüfen. Durch Ansprechen einer dritten Station + kann oft schnell geklärt werden, welche Rechner/Box-Verbindung + defekt sein muß. + + - Verbindung der Boxen untereinander defekt. + Abhilfe: Fehlende Verbindung, Masseschluß und Dreher (keine 1:1 Ver­ + bindung) überprüfen und beheben. + Hinweis: Liegt z.B. ein Masseschluß vor, so kann es durchaus sein, daß + Boxen, die nicht in der Nähe des Masseschluß stehen noch mitei­ + nander arbeiten können. Man kann aus der Tatsache, daß zwei + Boxen miteinander arbeiten können, also nicht schließen, daß man + nicht nach diesem Fehler suchen muß. + + + Beispiel: + + Auf #on("bold")#list (4/public)#off("bold")# erfolgt keine Reaktion. + + + - Station 4 ist während dieser Sendung zusammengebrochen. + Abhilfe: Station 4 wieder starten. Die Bearbeitung des 'list'-Kommandos + wird automatisch wieder aufgenommen. + + - PUBLIC auf Station 4 ist nicht im Managerzustand. + Abhilfe: PUBLIC in den Managerzustand versetzen. + + + Hinweis: Das Netz hat nocht nicht die volle Sendungslogik des EUMEL. So + wird nur ca. 10 Minuten lang versucht, eine Sendung zuzustellen. + Danach wird die Sendung gelöscht. Ist dies eingetreten, so muß + das list-Kommando erneut gegeben werden. + + - Fehler in der Netzhardware. + Überprüfen Sie, ob + + - die Boxen eingeschaltet sind, + - die Bereitlampe blinkt (wenn nicht: RESET an der Box) + - die V24-Kabel richtig stecken, + - die Boxen untereinander verbunden sind (1 zu 1 Verbindungen der 5 + poligen Diodenbuchsen). + + + - Die Netzsoftware ist auf einen nicht vorhergesehenen Fehler gelaufen. + Dieser wird im Report vermerkt. + Abhilfe: Geben Sie in der Task #on("bold")#net#off("bold")# das Kommando #on("bold")#start#off("bold")#. Dadurch wird die + Netzsoftware neu gestartet. Alle Netzkommunikationen dieser + Station gehen verloren. + + + Beispiel: + + Auf #on("bold")#list (4/public)#off("bold")# erfolgt die Meldung 'Collectortask fehlt'. + + - In der Task 'configurator' wurde das Kommando 'define collector' (siehe 3.2) + nicht gegeben. + + - Die Task 'net port' existiert nicht mehr. + Abhilfe: Kommando 'start' in der Task 'net'. + + + Beispiel: + + Nach #on("bold")#fetch ("hugo",4/public)#off("bold")# sind Teile von der Datei "hugo" verfälscht. + + - Die V24-Verbindung zur Box ist nicht in Ordnung. + Abhilfe: Abstand zwischen Rechner und Box verkürzen; Baudrate ernie­ + drigen; Durch Wechseln der V24-Schnittstelle feststellen, ob + diese defekt ist. + Hinweis: Die Verbindung zwischen den Boxen ist durch Prüfsummen abge­ + sichert (Hardware). + +#headodd# + +#center#Teil 2: Arbeitsweise der Netzsoftware#right#% + + +#end# +#page# +#type("triumb12")# + +Teil 2: Arbeitsweise der Netzsoftware + + +1. Die Netztask #type ("trium8")# + +In diesem Kapitel wird beschrieben, wie eine Netztask in das System +eingebettet ist und welche Aufgaben sie hat. Unter Einhaltung dieser +Konzepte kann die ausgelieferte Netztask so geändert werden, daß sie +beliebige andere Netzhardware unterstützt. Z.Zt. ist die Netzsoftware noch +nicht so gegliedert, daß nur eine hardwareabhängige Komponente ausgetauscht +werden muß. + +Die Kommunikation zwischen Tasks im EUMEL-Betriebssystem basiert auf einem +Rendevouskonzept: Die Zieltask einer Sendung muß empfangsbereit sein, wenn die +Quelltask sendet. + +Die Kommunikationsprozeduren auf der niedrigsten Ebene sind 'send' (Senden) +und 'wait' (Warten auf Empfang). Bei der Kommunikation werden eine Integer +'code' und ein Datenraum 'dr' übergeben. 'code' muß >= 0 sein, da negative +Codes systemintern verwandt werden. Ist die empfangende Task an einen Kanal +gekoppelt ('continue'), so führt eine Zeicheneingabe auf diesem Kanal dazu, +daß eine +Sendung mit dem Code -4 ankommt. Die Eingabedaten müssen mit den üblichen +Eingabeprozeduren ('inchar' u.s.w.) abgeholt werden. Der übermittelte Datenraum +und die Absendertask sind dabei ohne Bedeutung und dürfen nicht interpretiert +werden. + +Die Prozedur 'send' hat einen Rückmeldeparameter, der besagt, ob die Sendung +übermittelt wurde. Gibt es die Zieltask nicht oder steht sie nicht im 'wait', so kann +die Sendung nicht übermittelt werden. + + +Ein Entwicklungskriterium für das EUMEL-Netz war es, möglichst wenig Unter­ +stützung von der virtuellen EUMEL-Maschine (EUMEL0) zu fordern, damit weit­ +gehend in ELAN programmiert werden kann. Dadurch ist es möglich eine (privili­ +gierte) Task mit der Netzabwicklung zu betrauen. + +Zunächst wird auf die EUMEL0-Unterstützung eingegangen: + +1.1. Es gibt die Prozedur 'define collector', mit der die für das Netz verantwort­ + liche Task der EUMEL0-Maschine bekannt gemacht wird. Diese Task wird im + folgenden Collector genannt. + +1.2. Es gibt die Prozedur 'define station', die für den Rechner eine Stationsnum­ + mer einstellt. Anhand dieser Nummer werden die Rechner eines Netzes un­ + terschieden. Das Einstellen bewirkt, daß für alle Tasks die Stationsnummer in + ihre Task-Id eingetragen wird (Task-Id's sind die Werte, die der Typ TASK + annehmen kann). + +1.3. Der Befehl 'station (task)' liefert die Stationsnummer der 'task'. So liefert z.B. + 'station (myself)' die Stationsnummer des eigenen Rechners. + +1.4. Eine Sendung, deren Zieltask in einem anderen Rechner liegt (also station + (ziel) <> station (myself)), wird auf die Collectortask geleitet. + +1.5. Es gibt eine Prozedur 'collected destination', die es dem Collector erlaubt, die + eigentliche Zieltask einer auf ihn geleiteten Sendung zu erfahren. + +1.6. Es gibt eine Variante der Prozedur 'send', die es dem Collector gestattet, der + Zieltask eine beliebige andere Task als Absender vorzumachen. + +1.7. Es gibt eine spezielle Task-Id 'collector', durch die der augenblicklich ein­ + gestellte Collector erreicht wird. Diese wird als Zieltask beim Aufruf der Ver­ + mittlungsdienste angegeben (siehe 2.5). Eine Sendung an 'collector' wird von + EUMEL0 an den derzeitigen Collector geschickt. + +Ein Collector kann also auf drei Wegen von den übrigen Tasks desselben Rechners +Sendungen erhalten: + + 1. Über ein normales Send (z.B. bei 'list (/"net port")', wenn "net port" der der­ + zeitige Collector ist), + + 2. über ein Send an die Task 'collector' (s.u.) und + + 3. als umgeleitete Sendung (z.B. bei 'list' an eine Task auf einem anderen + Rechner). + +Der Collector kann diese Fälle anhand von 'collected destination' unterscheiden. + +Die Punkte 1.4...1.6 dienen dazu, den Collector für über Netz kommunizierende +Task unsichtbar zu machen: Der Collector taucht nicht als Ziel oder Quelle von +Sendungen auf. Das ist notwendig, damit normale Tasks sich nicht darum kümmern +müssen, ob eine Sendung übers Netz geht oder im eigenen Rechner bleibt. + +Wenn ein Datenraum an einen anderen Rechner geschickt wird, muß der gesamte +Inhalt (z. Zt. max. 1 MB) übertragen werden. Dies macht bei der üblichen Netz­ +hardware eine Zerlegung in Packete nötig (siehe Systemhandbuch 173, Teil 4, +Punkt 5). Für Netze über V24-Kanäle stehen spezielle Blockbefehle zur verfü­ +gung: + +1.8. blockin / blockout (dr,seite,512+abstand,anzahl,rest) + + Es werden maximal 'anzahl' Bytes transferiert. In 'rest' wird zurückgemeldet, + wieviel Bytes nicht bearbeitet wurden (z.B. weil der Kanal nichts anliefert). + Bearbeitet werden die Bytes + + 'seite' * 512 + 'abstand' + + bis maximal + + 'seite' * 512 + 'abstand' + 'anzahl' - 1 + + Der Kanal, an den die Task gekoppelt ist, wird dabei über Stream-IO (d.h. + 'incharety' bei 'blockin' bzw. 'out' bei 'blockout') angesprochen. + + Hinweis: Die Anforderung darf nicht über Seitengrenze gehen, d.h. + + 'abstand' + 'anzahl' <= 512 + + muß erfüllt sein. + + +Eine Netzsendung läuft wie folgt ab: + +Die Task q auf Rechner rq mache ein 'send' an die Task z auf Rechner rz. + +1. Die Prozedur send ist ein EUMEL0-Befehl. Die EUMEL0-Ebene erkennt, daß + die Sendung an die Station rz geht, da die Stationsnummer in der Task-Id + enthalten ist. Daher wird die Sendung zum Collector, den EUMEL0 wegen 'de­ + fine collector' kennt, umgeleitet. + +2. Die Task Collector empfängt über 'wait' den Datenraum, den Sendecode und + die Absendertask q. Die Zieltask z erfährt sie durch 'collected destination'. + +3. Der Collector nimmt Kontakt mit dem Collector des Rechner rz, dessen Sta­ + tionsnummer ja 'station(z)' ist, auf und Übermittelt diesem Sendecode, Quelltask + (q), eigentliche Zieltask (z) und den Datenraum. Da die Collectoren in ELAN + geschrieben sind, können sie an beliebige Netzhardware und Protokolle ange­ + paßt werden. + +4. Der Collector auf Rechner rz verwendet das spezielle 'send', um der Zieltask die + Sendung zuzustellen. Dadurch erscheint nicht der Collector sondern die Task q + als Absender der Sendung. + +Zur Abwicklung der Vermittlungsebene (Teil 1: 2.4) muß der Collector noch +spezielle Funktionen beherrschen. Diese sind + + der /-Operator (Taskname in Task-Id wandeln) und + die name-Prozedur (Task-Id in Namen wandeln). + +Der /-Operator macht eine Sendung an den 'collector', wobei im Datenraum der +Name der Task steht und der Sendecode gleich der Stationsnummer ist (siehe +Quellcode 173, Packet tasks). Der Collector setzt sich mit dem Collector dieser Sta­ +tion in Verbindung, damit dieser die Task-Id ermittelt und zurückschickt. Der +eigene Collector schickt dann dem /-Operator als Antwort einen Datenraum, der +die Task-Id enthält. + +Umgekehrt läuft 'name' ab: Wenn die Task-Id von einer fremden Station ist, +schickt 'name' eine Sendung an den 'collector', wobei im Datenraum die Task-Id +steht und Sendecode = 256 ist. Der Collector entnimmt die Stationnummer der +Task aus der Task-Id und läßt sich vom entsprechenden Collector den Tasknamen +geben. Dieser wird der 'name'-Prozedur im Antwortdatenraum übergeben. + +#type ("triumb12")#2. Ebenen #type("trium8")# + +In diesem Kapitel werden die Protokollebenen für das Netz beschrieben, wie +sie die ausgelieferte Netzsoftware benutzt und erwartet. Bei anderer +Netzhardware müssen die Ebenen 1 bis 3 ausgetauscht werden. Unter Einhaltung +der im vorigen Kapitel beschriebenen Randbedingungen können auch die höheren +Ebenen geändert werden. + + +2.1 Physikalische Ebene + + 2.1.1 Station <--> Box + + V24-Schnittstelle mit RTS/CTS-Handshake. Vollduplex. + + 2.1.2 Box <--> Box + + RS422 über 2 verdrillte Leitungspaare (Takt und Daten). + +2.2 Verbindungsebene + + 2.2.1 Station <--> Box + + Asynchron + 8 Bit + Even Parity + 2400/4800/9600/19200 Baud (einstellbar über Lötbrücken) + + 2.2.2 Box <--> Box + + SDLC + 400 KBaud + +2.3 Netzebene + + 2.3.1 Station <--> Box + + Telegrammformat: STX, , , , <(n-4) byte> + + ist Längenangabe ( 8 <= n <= 160) + , sind Stationsnummern. Diese müssen an den je­ + weiligen Boxen über Lötbrücken eingestellt sein. + + Box --> Station: + + Ein Telegramm kommt nur bei der Station an, bei deren Box die + Nummer eingestellt ist. Dadurch ist ein Mithören fremder + Übertragungen nicht möglich (Datenschutz). + + Zwischen Telegrammen können Fehlermeldungen der Box (Klartext) + übermittelt werden (z.B. 'skipped x', wenn ein STX von der Box er­ + wartet wurde, aber 'x' von der Station ankommt). + + Station --> Box: + + Ein Telegramm wird nur abgeschickt, wenn mit der einge­ + stellten Nummer übereinstimmt (Datenschutz: Man kann nicht eine + beliebige Station zu sein vorschwindeln, es sei denn man hat physi­ + schen Zugriff zur Box und stellt dort die Stationsnummer um). + + 2.3.2 Box <--> Box + + Telegrammformat: FRAME, , , , + + + Eine Längenangabe ist nicht nötig, da SDLC eine Rekonstruktion der + Länge erlaubt. + + Telegramme mit falschen CRC-Code werden vernichtet. Auf höheren + Ebenen muß dies durch Zeitüberwachung erkannt und behandelt + werden. + + +2.4 Transportebene + + Diese Ebene wickelt das Rendevous zwischen einer Task, die 'send' macht, + und einer Task, die im 'wait' steht, ab (siehe: EUMEL-Systemhandbuch). + + Der im 'send' angegebene Datenraum wird als Folge von Seiten (im + EUMEL-Sinne: Pagingeinheit und Allokiereinheit) übermittelt, wobei jede Seite + noch in 64 Byte große Stücke zerlegt wird. Es werden nur echt allokierte Seiten + übermittelt. Um nicht jedes Telegramm voll qualifizieren zu müssen, wird + zunächst eine Art virtuelle Verbindung durch ein OPEN-Telegramm eröffnet. + Danach folgen variable viele DATA-Telegramme. Beide Sorten werden durch + QUIT-Telegramme quittiert, um folgende Funktionen zu ermöglichen: + + Flußkontrolle (z.B. Zielrechner langsam) + Wiederaufsetzen (verlorene Telegramme) + Abbruch (z.B. weil Zieltask inzwischen beendet). + + Ein CLOSE-Telegramm ist nicht nötig, da das letzte DATA-Telegramm als + solches erkannt werden kann (siehe unten). + + 2.4.1 OPEN-Telegramm + + STX, 20, , , , , , + , , + + , siehe 2.3.1 + + Die Stromnummer identifiziert die virtuelle Verbindung. + Sie muß in den QUIT-Telegrammen angegeben wer­ + den. + + -1 (Kennzeichen für OPEN) + + Nummer der ersten echt allokierten Seite des Datenra­ + ums (=-1, falls Nilspace) + + Taskid der sendenden Task + + Taskid der empfangenden Task + + Wert des im 'send' angegebenen Codes. + + 2.4.2 DATA-Telegramm + + STX, 74, , , , , <64 byte> + + wird von Telegramm zu Telegramm hochgezählt. Dient + der Überwachung gegen verlorengegangene Telegramme + bzw. durch Zeitüberwachung verdoppelter Telegramme. + + Nummer der x.ten echt allokierten Seite des Datenra­ + ums. (x = (+16) DIV 8). + + <64 byte> Nutzinformation. Diese gehört zur Adresse a des Daten­ + raums. + + a = N ( DIV 8 + 1) * 512 + + ( MOD 8) * 64 + + wobei N (x) die Nummer der x.ten Seite ist. + + Aus den Formeln ergibt sich, daß diese Nummer schon in + einem vorhergehenden DATA/OPEN-Telegramm über­ + mittelt wurde (im Feld ). + + 2.4.3 QUIT-Telegramm + + STX, 8, , , , + + muß die Stromnummer sein, die in dem OPEN/DATA- + Telegramm stand, das quittiert wird. + + 0 : ok. Nächstes Telegramm schicken. + + -1: Übertragung neu starten (mit OPEN), weil die + Empfangsstation das OPEN nicht erhalten hat. + + -2: Übertragung ca. 20 Telegramme zurücksetzen. + + -3: Übertragung abbrechen. + + +2.5 Vermittlungsebene + + Diese Ebene ist dafür zuständig, Tasknamen von Task auf anderen Stationen + in Taskids (Werte des Typs TASK) zu wandeln und umgekehrt. Hierzu wird im + entsprechenden OPEN-Telegramm der Code -6 (bzw. -7) als + eingetragen. Die Netzempfangstask erkennt diese Codes und wickelt die + Aufgaben selbst ab, sodaß es dabei nicht nötig ist, irgendeine Taskid der + Zielstation zu kennen. + + Dieses Verfahren ist möglich, weil im 'send' nur positive Codes erlaubt sind. + +2.6 Höhere Ebenen + + Höhere Ebenen sind nicht mehr netzspezifisch. Sie basieren alle auf dem + Send/Wait-Konzept des EUMEL. So gibt es z.B. den 'global manager', der + Aufbewahrung und Zugriff von Dateien in einer Task regelt. Dabei darf diese + Task (bei der Variante 'free global manager') auf einer beliebigen Station im + Netz liegen. Wegen des Rendevous-Konzepts können beliebige Sicherheit­ + strategien benutzt werden (z.B.: Keine Dateien an Station 11 ausliefern). Von + großen Wert ist z.B., daß man ohne weiteres das Archiv (Floppylaufwerk) einen + anderen Station anmelden und benuzten kann, wodurch eine einfache Kon­ + vertierung von Floppyformaten möglich ist. Dies ist möglich, weil auch die Ar­ + chiv-Task der Stationen sich an das Globalmanagerprotokoll halten. + + +#type("triumb12")# +Bemerkungen#type("trium8")# + +Fehlerbehandlung besteht bis Ebene 3 darin, fehlerhafte Telegramme einfach zu +entfernen. Die Ebene 4 überwacht den Netzverkehr sowieso über Timeouts, die +eine Wiederhohlung eines Telegrammes bewirken, wenn die Quittung ausbleibt. + +Da bei der sendenden Station der ganze Datenraum zur Verfügung steht, ist eine +Fenstertechnik (wie bei HDLC) nicht nötig. Es kann zu jedem Zeitpunkt um beliebig +viele Telegramme zurückgesetzt werden. + +Da im EUMEL eine Textdatei ein Datenraum mit sehr komplexer Struktur ist (wegen +der Insert/Delete-Möglichkeiten, ohne den Rest der Datei zu schieben), ist es ein +hoher Aufwand, von einem fremden Betriebssytem her Textdateien ins EUMEL- +Netz zu senden. Für solche Zwecke muß noch eine einfachere Dateistruktur defi­ +niert werden und entsprechende Dateikonverter erstellt werden. + + + +#type("triumb12")#3. Stand der Netzsoftware #type("trium8")# + +Das EUMEL-System wickelt die Prozedur #on("bold")#send#off("bold")# über das Netz ab, wenn die +Stationsnummer der Zieltask ungleich der eigenen Stationsnummer ist. Umge­ +kehrt kann man der von der Prozedur #on("bold")#wait#off("bold")# gelieferten Absendertask die Absen­ +derstation entnehmen (siehe Prozedur #on("bold")#station#off("bold")# in Abschnitt 3). + +Nicht unterstützt wird z.Zt. die Logik der Prozeduren #on("bold")#call#off("bold")# und #on("bold")#pingpong#off("bold")#. Diese +funktionieren nur in der gewohnten Weise, wenn die Zieltask in #on("bold")#wait#off("bold")# steht. Ist +die Zieltask länger als ca. 10 Minuten #on("bold")#busy#off("bold")# oder nicht mehr vorhanden, geht die +Sendung einfach verloren (Gefordert ist: bei #on("bold")#call#off("bold")#: immer wieder versuchen; bei #on("bold")# +pingpong#off("bold")#: Rückmeldung -2). + +Wegen dieser Einschränkung kann man z.B. ein sicheres Drucken von Station a +auf einen Drucker der Station b nur durch einen eigenen Spoolmanager auf +Station a verwirklichen. Die Einrichtung eines solchen Managers ist allerdings +sowieso sinnvoll, damit man + +- das normale 'print'-Kommando verwenden kann (statt z.B. save ("xxx", +4/printer);) und +- nicht zu warten braucht, bis die Datei übers Netz gesendet ist. + + -- cgit v1.2.3