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;
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 ← ProcessorFace.GetClockPulses[];
Alto Pulses are short
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;
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;
Formerly in DummyForwarder, but more properly here...
DontForwardPupBuffer:
PUBLIC
PROCEDURE [b: BufferDefs.PupBuffer] =
BEGIN
BufferDefs.ReturnFreeBuffer[b];
IF CommFlags.doStats THEN StatsDefs.StatIncr[statPupNotForwarded];
END;
END.