DIRECTORY
Process USING [SetTimeout, MsecToTicks],
BufferDefs USING [AdjustBufferSize, DataWordsPerPupBuffer, PupBuffer, BufferAccessHandle, MakeBufferPool, FreeBufferPool],
CommFlags USING [doDebug],
CommUtilDefs USING [GetEthernetHostNumber],
DriverDefs USING [GetGiantVector, Glitch, Network, RouterObject, SetPupRouter, MaybeGetFreePupBuffer, GetDeviceChain, CommPackageGo, CommPackageOff],
GermSwap USING [switches],
PupDefs USING [ --defaultNumberOfNetworks,-- SetPupContentsWords, PupRouterBroadcastThis],
PupRouterDefs USING [BeSurePupIsOn, checksum, dataWordsPerPup, firstSocket, GetRoutingTableEntry, inThings, maxHop, outThings, PupBroadcaster, PupChecksums, PupErrors, PupInputer, PupRouterIn, PupRouterOut, routerIsActive, routingTable, RoutingTable, RoutingTableEntry, RoutingTableObject, RoutingTableSeq, Timeout],
PupStream USING [],
PupTypes USING [PupNetID, gatewaySoc];
PupRouterCold:
MONITOR
LOCKS routerLock
IMPORTS GermSwap, BufferDefs, CommUtilDefs, DriverDefs, Process, PupDefs, PupRouterDefs
EXPORTS PupStream, PupDefs, PupRouterDefs
SHARES BufferDefs
= PUBLIC BEGIN OPEN PupRouterDefs;
Network: TYPE = DriverDefs.Network;
routerLock: PUBLIC MONITORLOCK;
routingTableUpdateTimeout: PUBLIC CONDITION;
probeResponse: PUBLIC CONDITION;
numberOfNetworks: PUBLIC CARDINAL ← 255--PupDefs.defaultNumberOfNetworks--;
pupUseCount: CARDINAL ← 0;
routerTimeoutFork: PROCESS;
pupBuffersToAllocate: CARDINAL ← 50;
pupBuffers: BufferDefs.BufferAccessHandle ← NIL;
doDebug: BOOLEAN = CommFlags.doDebug;
router: DriverDefs.RouterObject ←
[input:
LOOPHOLE[PupInputer], broadcast:
LOOPHOLE[PupBroadcaster],
addNetwork: AddNetwork, removeNetwork: RemoveNetwork,
stateChanged: StateChanged];
CantChangeBuffersWhenActive: PUBLIC ERROR = CODE;
AdjustBufferParms:
PUBLIC
SAFE
PROCEDURE [bufferPoolSize, bufferSize:
CARDINAL] =
TRUSTED BEGIN
IF doDebug
AND pupUseCount # 0
THEN
DriverDefs.Glitch[CantChangeBuffersWhenActive];
IF bufferPoolSize # 0 THEN pupBuffersToAllocate ← bufferPoolSize;
IF bufferSize # 0 THEN BufferDefs.AdjustBufferSize[bufferSize];
END;
PupPackageMake:
PUBLIC
ENTRY
SAFE
PROCEDURE =
TRUSTED
BEGIN
routing: RoutingTable;
firstNetwork: Network;
IF (pupUseCount ← pupUseCount + 1) > 1 THEN RETURN;
DriverDefs.CommPackageGo[];
pupBuffers ← BufferDefs.MakeBufferPool[
total: pupBuffersToAllocate, reserve: 0];
dataWordsPerPup ← BufferDefs.DataWordsPerPupBuffer[];
firstNetwork ← DriverDefs.GetDeviceChain[];
routing ← NEW[RoutingTableSeq[numberOfNetworks + 1]]; -- allocates network zero too
routingTable ← routing;
routerIsActive ← TRUE;
IF doDebug THEN DriverDefs.GetGiantVector[].pupRoutingTable ← routing;
FOR i:
CARDINAL
IN [0..routing.length)
DO
routing[i] ← [net: [i], hop: maxHop + 1, time: 210, route:, network: NIL];
ENDLOOP;
The first network on the chain becomes network zero.
FOR network: Network ← firstNetwork, network.next
UNTIL network =
NIL
DO
IF network.hostNumber=0
THEN
BEGIN -- Probably a DLion (or something else without an EthernetOne)
network.hostNumber ← CommUtilDefs.GetEthernetHostNumber[];
END;
AddNetwork[network];
ENDLOOP;
DriverDefs.SetPupRouter[@router];
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.
Unfortunately, it is more complicated that than for the DLions since OISCP sets up the network number and the answer to the first probe may get lost if the Gateway doesn't have our entry in it 8to48 cache in the driver.
FOR i:
CARDINAL
IN [0..10)
DO
gotRoutingPup: BOOLEAN ← FALSE;
ProbeForRoutingInfo[];
WAIT probeResponse;
FOR i:
CARDINAL
IN [0..routing.length)
DO
IF routing[i].network # NIL AND routing[i].hop # 0 THEN gotRoutingPup ← TRUE;
ENDLOOP;
IF gotRoutingPup THEN EXIT;
ENDLOOP;
END;
ProbeForRoutingInfo:
PROCEDURE =
BEGIN
b: BufferDefs.PupBuffer;
b ← DriverDefs.MaybeGetFreePupBuffer[];
IF b = NIL THEN RETURN;
b.bypassZeroNet ← FALSE;
b.pupType ← gatewayRequest;
b.pupID ← [0, 0];
b.dest.socket ← b.source.socket ← PupTypes.gatewaySoc;
PupDefs.SetPupContentsWords[b, 0];
PupDefs.PupRouterBroadcastThis[b];
END;
PupPackageDestroy:
PUBLIC
SAFE
PROCEDURE =
TRUSTED
BEGIN
IF doDebug THEN BeSurePupIsOn[];
IF PupPackageDestroyLocked[] THEN RETURN;
JOIN routerTimeoutFork;
IF doDebug
THEN
DriverDefs.GetGiantVector[].pupRoutingTable ← DESCRIPTOR[NIL, 0];
BufferDefs.FreeBufferPool[pupBuffers];
DriverDefs.CommPackageOff[];
END;
PupPackageDestroyLocked:
ENTRY
PROCEDURE
RETURNS [
BOOLEAN] =
INLINE
BEGIN
IF (pupUseCount ← pupUseCount - 1) # 0 THEN RETURN[TRUE];
DriverDefs.SetPupRouter[NIL];
routerIsActive ← FALSE;
NOTIFY routingTableUpdateTimeout;
RETURN[FALSE];
END;
GetPupPackageUseCount:
PUBLIC
SAFE
PROCEDURE
RETURNS [
CARDINAL] =
CHECKED BEGIN RETURN[pupUseCount]; END;
AddNetwork:
PROCEDURE [network: Network] =
BEGIN
net: PupTypes.PupNetID ← [network.netNumber.b];
rte: RoutingTableEntry;
IF ~network.alive THEN RETURN;
IF routingTable[0].network =
NIL
THEN
routingTable[0] ← [net: [0], hop: 0, time: 0, route: [0], network: network];
rte ← GetRoutingTableEntry[net];
IF rte #
NIL
THEN
rte^ ← [net: net, hop: 0, time: 0, route: [0], network: network];
END;
RemoveNetwork:
PROCEDURE [network: Network] =
BEGIN
probe: BOOLEAN ← FALSE;
FOR i:
CARDINAL
IN [0..routingTable.length)
DO
IF routingTable[i].network # network THEN LOOP;
routingTable[i] ←
[net: [i], hop: maxHop + 1, time: 210, route:, network: NIL];
probe ← TRUE;
ENDLOOP;
IF probe THEN ProbeForRoutingInfo[];
END;
StateChanged:
PROCEDURE [network: Network] =
BEGIN RemoveNetwork[network]; AddNetwork[network]; 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
SAFE
PROCEDURE [
on, seeBroadcast: BOOLEAN,
proc: PROCEDURE [BufferDefs.PupBuffer] RETURNS [error: BOOLEAN]] = TRUSTED
BEGIN
inThings.watcherIsWatching ← on;
inThings.watcherSeesBroadcast ← seeBroadcast;
inThings.watcherCallsThis ← proc;
END;
UseNullChecksumMicrocode:
PUBLIC
PROCEDURE =
BEGIN PupRouterDefs.checksum ← none; END;
UseSoftwareChecksumMicrocode:
PUBLIC
PROCEDURE =
BEGIN PupRouterDefs.checksum ← software; END;
UseAltoChecksumMicrocode:
PUBLIC
PROCEDURE =
BEGIN PupRouterDefs.checksum ← alto; END;
UsePrincOpsChecksumMicrocode:
PUBLIC
PROCEDURE =
BEGIN PupRouterDefs.checksum ← princOps; END;
initialization
START PupRouterDefs.PupRouterIn;
START PupRouterDefs.PupRouterOut;
START PupRouterDefs.PupChecksums;
START PupRouterDefs.PupErrors;
Process.SetTimeout[@routingTableUpdateTimeout, Process.MsecToTicks[30000]];
Process.SetTimeout[@probeResponse, Process.MsecToTicks[500]];
IF doDebug
THEN
BEGIN DriverDefs.GetGiantVector[].firstPupSocket ← @firstSocket; END;
IF NOT GermSwap.switches[c] THEN PupPackageMake[];
END.