-- File: PupRouterCold.Mesa, Last Edit: -- MAS Apr 18, 1980 6:13 PM -- HGM January 5, 1980 3:17 PM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY CommUtilDefs: FROM "CommUtilDefs" USING [ AllocateHeapNode, FreeHeapNode, SetTimeout, MsecToTicks], PupRouterDefs: FROM "PupRouterDefs" USING [ PupRouterIn, PupRouterOut, PupChecksums, PupErrors, inThings, outThings, checksum, GetPupRoutingTable, pupRouterIsActive, BeSurePupIsOn, Timeout, pupRoutingTable, pupRoutingTableOut, PupRoutingTableEntry, firstSocket, dataWordsPerPup, maxHop, PupInputer, PupBroadcaster], DriverDefs: FROM "DriverDefs" USING [ doDebug, giantVector, Network, RouterObject, SetPupRouter, CommPackageGo, CommPackageOff, GetDeviceChain], PupStream: FROM "PupStream", -- EXPORTS PupDefs: FROM "PupDefs" USING [ defaultNumberOfNetworks, GetFreePupBuffer, SetPupContentsWords, PupRouterBroadcastThis], BufferDefs: FROM "BufferDefs" USING [DataWordsPerPupBuffer, PupBuffer], PupTypes: FROM "PupTypes" USING [gatewaySoc]; PupRouterCold: MONITOR LOCKS routerLock IMPORTS CommUtilDefs, PupRouterDefs, DriverDefs, PupDefs, BufferDefs EXPORTS PupStream, PupDefs, PupRouterDefs SHARES BufferDefs = PUBLIC BEGIN OPEN PupRouterDefs; routerLock: PUBLIC MONITORLOCK; routingTableUpdateTimeout: PUBLIC CONDITION; probeResponse: PUBLIC CONDITION; numberOfNetworks: PUBLIC CARDINAL ← PupDefs.defaultNumberOfNetworks; pupUseCount: CARDINAL ← 0; routerTimeoutFork: PROCESS; doDebug: BOOLEAN = DriverDefs.doDebug; pupRouter: DriverDefs.RouterObject ← [ input: LOOPHOLE[PupInputer], broadcast: LOOPHOLE[PupBroadcaster], addNetwork: AddNetwork, removeNetwork: RemoveNetwork ]; PupPackageMake: PUBLIC ENTRY PROCEDURE = BEGIN b: BufferDefs.PupBuffer; i: CARDINAL; routing: DESCRIPTOR FOR ARRAY OF PupRoutingTableEntry; network, firstNetwork: DriverDefs.Network; IF (pupUseCount←pupUseCount+1)>1 THEN RETURN; DriverDefs.CommPackageGo[]; dataWordsPerPup ← BufferDefs.DataWordsPerPupBuffer[]; network ← firstNetwork ← DriverDefs.GetDeviceChain[]; routing ← DESCRIPTOR [ -- allocates network zero too CommUtilDefs.AllocateHeapNode[(numberOfNetworks+1)*SIZE[PupRoutingTableEntry]], numberOfNetworks+1]; pupRoutingTable ← pupRoutingTableOut ← routing; pupRouterIsActive ← TRUE; IF doDebug THEN DriverDefs.giantVector.pupRoutingTable ← routing; FOR i IN [0..LENGTH[routing]) DO routing[i] ← [hop: maxHop+1, time: 210, route: , network: NIL]; ENDLOOP; -- The first network on the chain becomes network zero. routing[0] ← [hop: 0, time: 0, route: [0], network: network]; UNTIL network=NIL DO IF network.netNumber#0 AND network.netNumber<LENGTH[pupRoutingTable] THEN pupRoutingTable[network.netNumber] ← [hop: 0, time: 0, route: [0], network: network]; network ← network.next; ENDLOOP; DriverDefs.SetPupRouter[@pupRouter]; routerTimeoutFork ← FORK Timeout[]; IF firstNetwork=NIL THEN RETURN; IF firstNetwork.device=local THEN RETURN; -- avoid hanging -- If we don't know which network we are connected to, probe for a routing -- info packet, but don't wait forever in case all of the Gateways are down. -- Everything should work (as far as we are concerned) if myNet is 0. This -- happens when all of the gateways are down. If a client program really -- needs to know its network number, it will have to take care of itself. -- Be sure to go around the loop at least once or we won't get an initial -- routing table if we already know our network number because it came from -- the switches. FOR i IN [0..10) DO b ← PupDefs.GetFreePupBuffer[]; b.bypassZeroNet ← FALSE; b.pupType ← gatewayRequest; b.pupID ← [0,i]; b.dest.socket ← b.source.socket ← PupTypes.gatewaySoc; PupDefs.SetPupContentsWords[b,0]; PupDefs.PupRouterBroadcastThis[b]; WAIT probeResponse; IF firstNetwork.netNumber#0 THEN EXIT; ENDLOOP; END; PupPackageDestroy: PUBLIC PROCEDURE = BEGIN IF doDebug THEN BeSurePupIsOn[]; IF PupPackageDestroyLocked[] THEN RETURN; JOIN routerTimeoutFork; CommUtilDefs.FreeHeapNode[BASE[pupRoutingTable]]; IF doDebug THEN DriverDefs.giantVector.pupRoutingTable ← DESCRIPTOR[NIL,0]; DriverDefs.CommPackageOff[]; END; PupPackageDestroyLocked: ENTRY PROCEDURE RETURNS [BOOLEAN] = INLINE BEGIN IF (pupUseCount←pupUseCount-1)#0 THEN RETURN[TRUE]; DriverDefs.SetPupRouter[NIL]; pupRouterIsActive ← FALSE; NOTIFY routingTableUpdateTimeout; RETURN[FALSE]; END; GetPupPackageUseCount: PUBLIC PROCEDURE RETURNS [CARDINAL] = BEGIN RETURN[pupUseCount]; END; AddNetwork: PUBLIC PROCEDURE [network: DriverDefs.Network] = BEGIN routing: DESCRIPTOR FOR ARRAY OF PupRoutingTableEntry ← GetPupRoutingTable[]; net: CARDINAL ← network.netNumber; IF net IN [0..LENGTH[routing]] THEN routing[net] ← [hop: 0, time: 0, route: [0], network: network]; END; RemoveNetwork: PUBLIC PROCEDURE [network: DriverDefs.Network] = BEGIN routing: DESCRIPTOR FOR ARRAY OF PupRoutingTableEntry ← GetPupRoutingTable[]; net: CARDINAL ← network.netNumber; IF net IN [0..LENGTH[routing]] THEN routing[net] ← [hop: 0, time: 0, route: [0], network: NIL]; END; -- Various junky routines that live here because this is very cold code SetPupStormy: PUBLIC PROCEDURE [new: BOOLEAN] = BEGIN outThings.outStormy ← inThings.inStormy ← new; END; SetBadPupProc: PUBLIC PROCEDURE [proc: PROCEDURE[BufferDefs.PupBuffer]] = BEGIN inThings.badChecksumProc ← proc; END; InspectIncomingPups: PUBLIC PROCEDURE [ new: BOOLEAN, proc: PROCEDURE[CARDINAL,BufferDefs.PupBuffer]] = BEGIN inThings.showIn ← new; inThings.inShower ← proc; END; InspectOutgoingPups: PUBLIC PROCEDURE [ new: BOOLEAN, proc: PROCEDURE[CARDINAL,BufferDefs.PupBuffer]] = BEGIN outThings.showOut ← new; outThings.outShower ← proc; END; InspectStrayPups: PUBLIC PROCEDURE [ on, seeBroadcast: BOOLEAN, proc: PROCEDURE[BufferDefs.PupBuffer] RETURNS [error: BOOLEAN]] = BEGIN inThings.watcherIsWatching ← on; inThings.watcherSeesBroadcast ← seeBroadcast; inThings.watcherCallsThis ← proc; END; SetPupCheckit: PUBLIC PROCEDURE [new: BOOLEAN] = BEGIN PupRouterDefs.checksum ← IF new THEN software ELSE none; END; UseAltoChecksumMicrocode: PUBLIC PROCEDURE = BEGIN PupRouterDefs.checksum ← alto; END; -- initialization START PupRouterDefs.PupRouterIn; START PupRouterDefs.PupRouterOut; START PupRouterDefs.PupChecksums; START PupRouterDefs.PupErrors; CommUtilDefs.SetTimeout[@routingTableUpdateTimeout,CommUtilDefs.MsecToTicks[30000]]; CommUtilDefs.SetTimeout[@probeResponse,CommUtilDefs.MsecToTicks[500]]; IF doDebug THEN BEGIN DriverDefs.giantVector.firstPupSocket ← @firstSocket; END; END.