-- File: PupRouterOut.mesa, Last Edit: HGM October 16, 1979 11:08 PM
-- Copyright Xerox Corporation 1979, 1980
DIRECTORY
StatsDefs: FROM "StatsDefs" USING [StatIncr],
CommUtilDefs: FROM "CommUtilDefs" USING [GetTicks],
PupRouterDefs: FROM "PupRouterDefs" USING [
routerLock, maxHop, OutThings,
PupRoutingTableEntry, BeSurePupIsOn, SetPupChecksum],
DriverDefs: FROM "DriverDefs" USING [
firstNetwork, doDebug, doShow, doStats, doStorms,
Glitch, Network, PutOnGlobalDoneQueue],
PupDefs: FROM "PupDefs" USING [
outgoingPup, zappedOutgoingPup, PupBuffer],
BufferDefs: FROM "BufferDefs",
PupTypes: FROM "PupTypes" USING [
allNets, allHosts, PupType,
PupAddress, PupHostID, PupNetID],
DriverTypes: FROM "DriverTypes" USING [bufferSeal];
PupRouterOut: MONITOR LOCKS PupRouterDefs.routerLock
IMPORTS StatsDefs, CommUtilDefs, PupRouterDefs, DriverDefs
EXPORTS PupRouterDefs, PupDefs
SHARES BufferDefs, DriverTypes =
BEGIN OPEN StatsDefs, PupRouterDefs, DriverDefs, PupDefs, PupTypes;
pupRoutingTableOut: PUBLIC DESCRIPTOR FOR ARRAY OF PupRoutingTableEntry;
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;
routing: POINTER TO PupRoutingTableEntry;
network: Network;
h: PupHostID;
IF doStats THEN StatIncr[statPupSent];
IF doDebug THEN BeSurePupIsOn[];
IF doDebug AND b.seal#DriverTypes.bufferSeal THEN Glitch[BufferSealBroken];
IF 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
lightning←-INTEGER[CommUtilDefs.GetTicks[] MOD 20B];
bolt←10;
END
ELSE BEGIN lightning←0; bolt←bolt+1; END;
END;
IF doShow AND outThings.showOut THEN outThings.outShower[zappedOutgoingPup,b];
PutOnGlobalDoneQueue[b];
IF doStats THEN StatIncr[statZappedP];
RETURN;
END;
-- Maybe we should do something for the local case?
b.pupTransportControl ← 0;
routing ← @pupRoutingTableOut[n];
network ← routing.network;
IF n ~IN [0..LENGTH[pupRoutingTableOut]) OR routing.hop>maxHop OR network=NIL THEN
BEGIN -- don’t know where to send it
IF doStats THEN StatIncr[statPupsSentNowhere];
IF n ~IN [0..LENGTH[pupRoutingTableOut]) OR network=NIL THEN
BEGIN -- Send him an error Pup, but beware of RequeueProc-- END;
PutOnGlobalDoneQueue[b];
RETURN; -- wait to see if there is an alternate path
END;
b.source.host ← [network.hostNumber]; -- tell the truth
b.source.net ← [network.netNumber];
IF doShow AND outThings.showOut THEN outThings.outShower[outgoingPup,b];
h ← routing.route;
IF h=0 THEN h ← b.dest.host; -- we are on the same net
IF 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
IF doStats THEN StatIncr[statPupBroadcast];
IF doDebug THEN BeSurePupIsOn[];
IF doDebug AND b.seal#DriverTypes.bufferSeal THEN Glitch[BufferSealBroken];
IF DriverDefs.firstNetwork=NIL THEN BEGIN PutOnGlobalDoneQueue[b]; RETURN; END;
b.allNets ← TRUE; -- this is where it gets turned on
b.network ← DriverDefs.firstNetwork;
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 b.bypassZeroNet AND network.netNumber=0 THEN
BEGIN PutOnGlobalDoneQueue[b]; RETURN; END; -- goes (slowly) around in circles
b.pupTransportControl ← 0;
b.dest.net ← b.source.net ← [network.netNumber];
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: DriverDefs.Network ← b.network;
temp: PupAddress;
IF 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 THEN b.dest.net ← [network.netNumber];
IF b.source.net=0 THEN b.source.net ← [network.netNumber];
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. -- PupRouterOut