-- File: PupRouterOut.mesa, Last Edit: BLyon January 16, 1981 4:08 PM DIRECTORY Inline USING [LowHalf], System USING [GetClockPulses], StatsDefs USING [StatIncr], PupRouterDefs USING [ routerLock, maxHop, OutThings, RoutingTableEntry, GetRoutingTableEntry, BeSurePupIsOn, SetPupChecksum], CommFlags USING [doDebug, doShow, doStats, doStorms], DriverDefs USING [GetDeviceChain, Glitch, Network, PutOnGlobalDoneQueue], PupDefs USING [outgoingPup, zappedOutgoingPup, PupBuffer], BufferDefs, PupTypes USING [allNets, allHosts, PupType, PupAddress, PupHostID, PupNetID], DriverTypes USING [bufferSeal]; PupRouterOut: MONITOR LOCKS PupRouterDefs.routerLock IMPORTS Inline, System, StatsDefs, PupRouterDefs, DriverDefs EXPORTS BufferDefs, PupRouterDefs, PupDefs SHARES BufferDefs, DriverTypes = BEGIN OPEN StatsDefs, PupRouterDefs, DriverDefs, PupDefs, PupTypes; -- EXPORTed TYPEs Network: PUBLIC TYPE = DriverDefs.Network; dataWordsPerPup: PUBLIC CARDINAL; outThings: PUBLIC OutThings ← [outStormy: FALSE, showOut: FALSE, outShower:]; -- parameters for killing packets lightning: INTEGER ← 30; bolt: INTEGER ← 10; BufferSealBroken: PUBLIC ERROR = CODE; IllegalPupLength: PUBLIC ERROR = CODE; PupRouterSendThis: PUBLIC ENTRY PROCEDURE [b: PupBuffer] = BEGIN IF b.dest.net = allNets AND b.dest.host = allHosts THEN BEGIN PupRouterBroadcastThis[b]; RETURN; END; SendUnlocked[b]; END; SneakySendUnlocked: PUBLIC PROCEDURE [b: PupBuffer] = JustSendUnlocked; JustSendUnlocked: INTERNAL PROCEDURE [b: PupBuffer] = BEGIN SendUnlocked[b]; END; SendUnlocked: INTERNAL PROCEDURE [b: PupBuffer] = BEGIN d: PupAddress ← b.dest; n: PupNetID ← d.net; rte: RoutingTableEntry; network: Network; h: PupHostID; IF CommFlags.doStats THEN StatIncr[statPupSent]; IF CommFlags.doDebug THEN BeSurePupIsOn[]; IF CommFlags.doDebug AND b.seal # DriverTypes.bufferSeal THEN Glitch[BufferSealBroken]; IF CommFlags.doStorms AND outThings.outStormy -- for debugging only AND (lightning ← lightning + 1) > bolt OR lightning < 0 THEN BEGIN IF lightning > bolt THEN BEGIN IF bolt > 100 THEN BEGIN mumble: LONG CARDINAL ← System.GetClockPulses[]; -- Alto Pulses are short lightning ← -INTEGER[Inline.LowHalf[mumble] MOD 20B]; bolt ← 10; END ELSE BEGIN lightning ← 0; bolt ← bolt + 1; END; END; IF CommFlags.doShow AND outThings.showOut THEN outThings.outShower[zappedOutgoingPup, b]; PutOnGlobalDoneQueue[b]; IF CommFlags.doStats THEN StatIncr[statZappedP]; RETURN; END; -- Maybe we should do something for the local case? b.pupTransportControl ← 0; rte ← GetRoutingTableEntry[n]; IF rte = NIL OR rte.hop > maxHop OR (network ← rte.network) = NIL THEN BEGIN -- don't know where to send it IF CommFlags.doStats THEN StatIncr[statPupsSentNowhere]; BEGIN -- Send him an error Pup, but beware of RequeueProc-- END; PutOnGlobalDoneQueue[b]; RETURN; -- wait to see if there is an alternate path END; IF CommFlags.doShow AND outThings.showOut THEN outThings.outShower[outgoingPup, b]; h ← rte.route; IF h = 0 THEN h ← b.dest.host; -- we are on the same net IF CommFlags.doDebug AND ((b.pupLength + 1)/2) > dataWordsPerPup + wordsPerPupHeader THEN DriverDefs.Glitch[IllegalPupLength]; SetPupChecksum[b]; network.encapsulatePup[b, h]; network.sendBuffer[b]; END; PupRouterBroadcastThis: PUBLIC PROCEDURE [b: PupBuffer] = BEGIN network: Network; IF CommFlags.doStats THEN StatIncr[statPupBroadcast]; IF CommFlags.doDebug THEN BeSurePupIsOn[]; IF CommFlags.doDebug AND b.seal # DriverTypes.bufferSeal THEN Glitch[BufferSealBroken]; b.network ← network ← DriverDefs.GetDeviceChain[]; IF network = NIL THEN {PutOnGlobalDoneQueue[b]; RETURN; }; b.allNets ← TRUE; -- this is where it gets turned on b.dest.host ← allHosts; PupBroadcaster[b]; END; -- b.network is already set up to the desired network PupBroadcaster: PUBLIC PROCEDURE [b: PupBuffer] = BEGIN network: Network ← b.network; IF ~network.alive OR (b.bypassZeroNet AND network.netNumber = [0, 0]) THEN BEGIN PutOnGlobalDoneQueue[b]; RETURN; END; -- goes (slowly) around in circles b.pupTransportControl ← 0; IF network.netNumber.b > 377B THEN b.dest.net ← b.source.net ← [0] ELSE b.dest.net ← b.source.net ← [network.netNumber.b]; b.source.host ← [network.hostNumber]; network.encapsulatePup[b, PupTypes.allHosts]; SetPupChecksum[b]; network.sendBuffer[b]; END; -- Pup is assumed to have arrived from somewhere else. We fixup defaults here. SwapPupSourceAndDest: PUBLIC PROCEDURE [b: PupBuffer] = BEGIN network: Network ← b.network; temp: PupAddress; IF CommFlags.doDebug AND b.seal # DriverTypes.bufferSeal THEN Glitch[BufferSealBroken]; temp ← b.source; b.source ← b.dest; b.dest ← temp; -- in case we are returning a broadcast packet IF b.dest.net = 0 AND network.netNumber.b < 400B THEN b.dest.net ← [network.netNumber.b]; IF b.source.net = 0 AND network.netNumber.b < 400B THEN b.source.net ← [network.netNumber.b]; IF b.source.host = PupTypes.allHosts THEN b.source.host ← [network.hostNumber]; END; ReturnPup: PUBLIC PROCEDURE [ b: PupBuffer, type: PupTypes.PupType, bytes: CARDINAL] = BEGIN SwapPupSourceAndDest[b]; SendPup[b, type, bytes]; END; wordsPerPupHeader: CARDINAL = 11; bytesPerPupHeader: CARDINAL = wordsPerPupHeader*2; GetPupContentsBytes: PUBLIC PROCEDURE [b: PupBuffer] RETURNS [bytes: CARDINAL] = BEGIN RETURN[b.pupLength - bytesPerPupHeader]; END; SetPupContentsBytes: PUBLIC PROCEDURE [b: PupBuffer, bytes: CARDINAL] = BEGIN IF bytes > dataWordsPerPup*2 THEN Glitch[IllegalPupLength]; b.pupLength ← bytes + bytesPerPupHeader; END; SetPupContentsWords: PUBLIC PROCEDURE [b: PupBuffer, words: CARDINAL] = BEGIN IF words > dataWordsPerPup THEN Glitch[IllegalPupLength]; b.pupLength ← words*2 + bytesPerPupHeader; END; SendPup: PUBLIC PROCEDURE [b: PupBuffer, type: PupType, bytes: CARDINAL] = BEGIN b.pupType ← type; SetPupContentsBytes[b, bytes]; PupRouterSendThis[b]; END; END.