<> <> <> <> DIRECTORY Basics USING [LongNumber], BufferDefs, CommFlags USING [doDebug, doShow, doStats, doStorms], DriverDefs USING [GetDeviceChain, Glitch, Network, PutOnGlobalDoneQueue], DriverTypes USING [bufferSeal], ProcessorFace USING [GetClockPulses], PupDefs USING [outgoingPup, zappedOutgoingPup, PupBuffer], PupRouterDefs USING [routerLock, maxHop, OutThings, RoutingTableEntry, GetRoutingTableEntry, BeSurePupIsOn, SetPupChecksum], PupTypes USING [allNets, allHosts, PupType, PupAddress, PupHostID, PupNetID], StatsDefs USING [StatIncr]; PupRouterOut: MONITOR LOCKS PupRouterDefs.routerLock IMPORTS BufferDefs, ProcessorFace, StatsDefs, PupRouterDefs, DriverDefs EXPORTS BufferDefs, PupRouterDefs, PupDefs SHARES BufferDefs, DriverTypes = BEGIN OPEN StatsDefs, PupRouterDefs, DriverDefs, PupDefs, PupTypes; <> Network: PUBLIC TYPE = DriverDefs.Network; dataWordsPerPup: PUBLIC CARDINAL; outThings: PUBLIC OutThings _ [outStormy: FALSE, showOut: FALSE, outShower:]; <> 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 _ ProcessorFace.GetClockPulses[]; <> lightning _ -INTEGER[LOOPHOLE[mumble, Basics.LongNumber].lowbits 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; <> 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; <> 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; <> 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; <> 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; <> 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; <> DontForwardPupBuffer: PUBLIC PROCEDURE [b: BufferDefs.PupBuffer] = BEGIN BufferDefs.ReturnFreeBuffer[b]; IF CommFlags.doStats THEN StatsDefs.StatIncr[statPupNotForwarded]; END; END.