PupForwarderImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Hal Murray, June 6, 1986 4:04:34 am PDT
Russ Atkinson (RRA) April 25, 1986 5:07:14 pm PST
DIRECTORY
CommDriver USING [Buffer, Network],
Endian USING [HWORD],
Process USING [Detach, Pause, priorityNormal, SecondsToTicks, SetPriority, Ticks],
Pup USING [allHosts, allNets, Host],
PupBuffer USING [Buffer, noChecksum, RoundUpForChecksum, WordsWithoutChecksum],
PupHop USING [maxHop],
PupInternal USING [CaptureForwarding, ProcessGatewayInfo, ProcessGatewayRequest, Route],
PupSocket USING [CreateServer, FreeBuffer, Get, SetRemoteAddress, Socket, waitForever],
PupSocketBackdoor USING [ReturnErrorNoFree],
PupWKS USING [gatewayInfo];
PupForwarderImpl: CEDAR MONITOR
IMPORTS Process, PupBuffer, PupInternal, PupSocket, PupSocketBackdoor = {
BYTE: TYPE = [0..100H);
Buffer: TYPE = PupBuffer.Buffer;
Network: TYPE = CommDriver.Network;
TempDriverBuffer: PROC [b: Buffer] RETURNS [CommDriver.Buffer] = TRUSTED INLINE {
RETURN[LOOPHOLE[b]]; };
Routing Table Updates
socket: PupSocket.Socket; -- Overlays the one in PupRouterImpl
RoutingSlurper: PROC = {
socket ← PupSocket.CreateServer[
local: PupWKS.gatewayInfo,
getTimeout: PupSocket.waitForever ];
PupSocket.SetRemoteAddress[socket, [Pup.allNets, Pup.allHosts, PupWKS.gatewayInfo]];
Process.SetPriority[Process.priorityNormal];
DO
b: Buffer ← PupSocket.Get[socket];
SELECT b.type FROM
gatewayRequest => PupInternal.ProcessGatewayRequest[b, FALSE];
gatewayInfo => IF PupInternal.ProcessGatewayInfo[b] THEN kick ← TRUE;
ENDCASE => NULL;
PupSocket.FreeBuffer[b];
ENDLOOP;
};
kick: BOOLFALSE;
RoutingDemon: PROC = {
second: Process.Ticks = Process.SecondsToTicks[1];
Process.SetPriority[Process.priorityNormal];
DO
FOR i: CARDINAL IN [0..15) UNTIL kick DO Process.Pause[2*second]; ENDLOOP;
kick ← FALSE;
PupInternal.ProcessGatewayRequest[NIL, FALSE];
ENDLOOP;
};
RealForwarder: PROC [b: Buffer] RETURNS [Buffer] = {
source: Network ← NARROW[b.ovh.network];
dest: Network;
immediate: Pup.Host;
old: Endian.HWORD;
IF b.hopCount = PupHop.maxHop THEN {
PupSocketBackdoor.ReturnErrorNoFree[b, tooManyHops, "Too many hops"];
BumpStats[source.index, 0, 0];
RETURN[b]; };
[dest, immediate] ← PupInternal.Route[b.dest];
IF dest = NIL THEN {
PupSocketBackdoor.ReturnErrorNoFree[b, cantGetThere, "No route to that net"];
BumpStats[source.index, 0, 0];
RETURN[b]; };
TRUSTED { old ← (@b.hWord[0]+magicOne)^; };
Negative indexing to address word holding hopCount
b.hopCount ← b.hopCount.SUCC;
UpdatePupChecksum[b, magicTwo, old];
b.ovh.encap ← dest.pup.getEncapsulation[dest, immediate];
dest.pup.send[dest, TempDriverBuffer[b], PupBuffer.RoundUpForChecksum[b.byteLength]];
BumpStats[source.index, dest.index, b.byteLength];
RETURN[b];
};
packetsForwarded: LONG CARDINAL ← 0;
bytesForwarded: LONG CARDINAL ← 0;
BumpStats: ENTRY PROC [source, dest: CARDINAL, bytes: CARDINAL] = {
IF dest # 0 THEN {
packetsForwarded ← packetsForwarded.SUCC;
bytesForwarded ← bytesForwarded + bytes; };
};
magicOne: INTEGER = -9; -- offset for pupTransportControl
magicTwo: CARDINAL = 1;
UpdatePupChecksum: PROC [b: Buffer, offset: INTEGER, oldValue: WORD] = TRUSTED {
words: NAT ← PupBuffer.WordsWithoutChecksum[b.byteLength];
checksumLoc: LONG POINTER TO Endian.HWORD ← @b.byteLength + words;
diff: WORD;
IF checksumLoc^ = PupBuffer.noChecksum THEN RETURN;
diff ← OnesSub[(@b.hWord[0] + (offset + (magicOne - magicTwo)))^, oldValue];
checksumLoc^ ← OnesAdd[checksumLoc^, LeftCycle[diff, words - offset]];
};
OnesAdd: PROC [a, b: CARDINAL] RETURNS [c: CARDINAL] = INLINE {
c ← a + b; IF c < a THEN c ← c + 1;
IF c = 177777B THEN c ← 0;
};
OnesSub: PROC [a, b: CARDINAL] RETURNS [c: CARDINAL] = INLINE {
c ← a + (-b - 1);
IF c < a THEN c ← c + 1;
IF c = 177777B THEN c ← 0;
};
LeftCycle: PROC [a, b: CARDINAL] RETURNS [c: CARDINAL] = INLINE {
c ← a;
THROUGH [0..(b MOD 16)) DO
IF c < 100000B THEN c ← c*2 ELSE c ← c*2 + 1;
ENDLOOP;
};
PupInternal.CaptureForwarding[RealForwarder];
TRUSTED { Process.Detach[FORK RoutingSlurper[]]; };
TRUSTED { Process.Detach[FORK RoutingDemon[]]; };
}.