<> <> <> <> DIRECTORY Basics USING [LongNumber], BufferDefs USING [OisBuffer], Checksums USING [SetChecksum, TestChecksum], CommunicationInternal USING [], CommFlags USING [doDebug, doStats, doStorms], CommUtilDefs USING [CopyLong], DriverDefs USING [ChangeNumberOfInputBuffers, DriverXmitStatus, GetDeviceChain, Glitch, MaybeGetFreeOisBuffer, Network, PutOnGlobalDoneQueue, RouterObject, SetOisRouter], OISCP USING [allHostIDs, CreditReceiveOisBuffer, EnqueueOis, MaybeGetFreeReceiveOisBufferFromPool, unknownNetID, unknownSocketID], OISCPConstants USING [routingInformationSocket], OISCPTypes USING [ bytesPerPktHeader, bytesPerPktText, maxBytesPerPkt, OISErrorCode, TransPortControl], Process USING [Yield], ProcessorFace USING [GetClockPulses], Router USING [AddNetwork, FindNetworkAndTransmit, FindDestinationRelativeNetID, ForwardPacket, RemoveNetwork, RoutingInformationPacket, RoutingTableOn, RoutingTableOff, SocketTable, StateChanged, XmitStatus], SocketInternal USING [SocketHandle], SpecialCommunication USING [RoutersFunction], NSAddress USING [broadcastHostNumber, GetProcessorID, HostNumber, NetworkAddress, nullNetworkNumber, NetworkNumber, SocketNumber], StatsDefs USING [StatIncr]; RouterImpl: MONITOR LOCKS socketRouterLock IMPORTS BufferDefs, Checksums, CommUtilDefs, DriverDefs, OISCP, Process, ProcessorFace, Router, NSAddress, StatsDefs EXPORTS BufferDefs, CommunicationInternal, OISCP, Router SHARES BufferDefs = BEGIN OPEN DriverDefs, OISCP, OISCPTypes, SocketInternal, StatsDefs; <> <> <> <> <> <> <> Network: PUBLIC TYPE = DriverDefs.Network; <> primaryMDS: PUBLIC BOOLEAN _ TRUE; -- we are in the primary MDS. checkIt: PUBLIC BOOLEAN _ TRUE; -- checksums on for everybody driverLoopback: BOOLEAN _ FALSE; -- loopback in router stormy: BOOLEAN _ FALSE; -- storms for debugging are not on routersFunction: PUBLIC SpecialCommunication.RoutersFunction _ vanillaRouting; myHostID: NSAddress.HostNumber; -- processor ID of this system element initialSpareSocketID: NSAddress.SocketNumber = [1001]; initialTransportControl: OISCPTypes.TransPortControl = [trace: FALSE, filler: 0, hopCount: 0]; <> <> <> oiscpRouter: DriverDefs.RouterObject _ [input: LOOPHOLE[ReceivePacket], broadcast: LOOPHOLE[SendBroadcastPacketToCorrectNet], addNetwork: Router.AddNetwork, removeNetwork: Router.RemoveNetwork, stateChanged: Router.StateChanged]; <> <> lightning: INTEGER _ 30; bolt: INTEGER _ 10; <> <> socketRouterLock: PUBLIC MONITORLOCK; <> <> <> spareSocketID: NSAddress.SocketNumber; <> socketTable: Router.SocketTable; <> IllegalOisPktLength: ERROR = CODE; <> <> <> <> <> AssignOisAddress: PUBLIC ENTRY PROCEDURE RETURNS [localAddr: NSAddress.NetworkAddress] = BEGIN localAddr _ [net: Router.FindDestinationRelativeNetID[NSAddress.nullNetworkNumber], host: myHostID, socket: spareSocketID]; IF (spareSocketID _ [spareSocketID + 1]) = NSAddress.SocketNumber[0] THEN spareSocketID _ initialSpareSocketID; END; -- AssignOisAddress <> <> <> <> AssignDestinationRelativeOisAddress: PUBLIC ENTRY PROCEDURE [destNet: NSAddress.NetworkNumber] RETURNS [localAddr: NSAddress.NetworkAddress] = BEGIN localAddr _ [net: Router.FindDestinationRelativeNetID[destNet], host: myHostID, socket: spareSocketID]; IF (spareSocketID _ [spareSocketID + 1]) = NSAddress.SocketNumber[0] THEN spareSocketID _ initialSpareSocketID; END; -- AssignDestinationRelativeOisAddress <> AddSocket: PUBLIC ENTRY PROCEDURE [sH: SocketHandle] = BEGIN MaybeIncreaseDriversBuffers: PROCEDURE = INLINE BEGIN previousSH: SocketHandle _ socketTable.first; UNTIL previousSH = NIL DO IF previousSH.pool.total > 0 THEN RETURN; previousSH _ previousSH.next; ENDLOOP; DriverDefs.ChangeNumberOfInputBuffers[TRUE]; -- TRUE => increase END; <> IF sH.pool.total > 0 THEN MaybeIncreaseDriversBuffers[]; sH.next _ socketTable.first; socketTable.first _ sH; socketTable.length _ socketTable.length + 1; END; -- AddSocket <> RemoveSocket: PUBLIC ENTRY PROCEDURE [sH: SocketHandle] = BEGIN MaybeDecreaseDriversBuffers: PROCEDURE = INLINE BEGIN previousSH _ socketTable.first; UNTIL previousSH = NIL DO IF previousSH.pool.total > 0 THEN RETURN; previousSH _ previousSH.next; ENDLOOP; DriverDefs.ChangeNumberOfInputBuffers[FALSE]; -- FALSE => decrease END; previousSH: SocketHandle; IF socketTable.first = sH THEN socketTable.first _ sH.next ELSE BEGIN previousSH _ socketTable.first; UNTIL previousSH = NIL DO IF previousSH.next = sH THEN BEGIN previousSH.next _ sH.next; EXIT; END; previousSH _ previousSH.next; ENDLOOP; END; socketTable.length _ socketTable.length - 1; IF sH.pool.total > 0 THEN MaybeDecreaseDriversBuffers[]; END; -- RemoveSocket <> <> SetOisStormy: PUBLIC PROCEDURE [new: BOOLEAN] = BEGIN stormy _ new; END; <> <> <> SetOisCheckit: PUBLIC PROCEDURE [new: BOOLEAN] = BEGIN checkIt _ new; END; <> <> <> SetOisDriverLoopback: PUBLIC PROCEDURE [new: BOOLEAN] = BEGIN driverLoopback _ new; END; -- SetOisDriverLoopback <> FindMyHostID: PUBLIC PROCEDURE RETURNS [NSAddress.HostNumber] = BEGIN RETURN[myHostID]; END; -- FindMyHostID GetOisPacketTextLength: PUBLIC PROCEDURE [b: BufferDefs.OisBuffer] RETURNS [CARDINAL] = BEGIN RETURN[b.ois.pktLength - bytesPerPktHeader]; END; <> SetOisPacketTextLength: PUBLIC PROCEDURE [b: BufferDefs.OisBuffer, len: CARDINAL] = BEGIN IF len IN [0..bytesPerPktText] THEN b.ois.pktLength _ len + bytesPerPktHeader ELSE IF CommFlags.doDebug THEN Glitch[IllegalOisPktLength]; END; -- SetOisPacketTextLength SetOisPacketLength: PUBLIC PROCEDURE [b: BufferDefs.OisBuffer, len: CARDINAL] = BEGIN IF len IN [bytesPerPktHeader..maxBytesPerPkt] THEN b.ois.pktLength _ len ELSE IF CommFlags.doDebug THEN Glitch[IllegalOisPktLength]; END; -- SetOisPacketLength <> <> <> <> <> <> <> <> <> <> SendPacket: PUBLIC PROCEDURE [b: BufferDefs.OisBuffer] = BEGIN IF CommFlags.doStorms AND stormy AND PacketHit[] THEN BEGIN DriverDefs.PutOnGlobalDoneQueue[b]; RETURN; -- for debugging only END; IF b.ois.destination.host = myHostID AND NOT driverLoopback THEN <> BEGIN IF NOT DeliveredToLocalSocket[b, TRUE] THEN -- TRUE -> copy this buffer BEGIN nullNetwork: Network = NIL; -- because of EXPORTed TYPEs bug <> IF CommFlags.doStats THEN StatIncr[statJunkOisForUsNoLocalSocket]; b.network _ nullNetwork; SendErrorPacket[b, noSocketOisErrorCode, 0]; END; <> <> DriverDefs.PutOnGlobalDoneQueue[b]; Process.Yield[]; END ELSE <> BEGIN <> <> <> b.ois.transCntlAndPktTp.transportControl _ initialTransportControl; IF checkIt THEN Checksums.SetChecksum[b] ELSE b.ois.checksum _ 177777B; [] _ Router.FindNetworkAndTransmit[b]; END; END; -- SendPacket <> <> <> <> ReceivePacket: PUBLIC PROCEDURE [b: BufferDefs.OisBuffer] = BEGIN badChecksum: BOOLEAN; incomingNet: Network; destHost: NSAddress.HostNumber _ b.ois.destination.host; broadcastPacket: BOOLEAN _ FALSE; IF b.ois.pktLength < OISCPTypes.bytesPerPktHeader THEN BEGIN IF CommFlags.doStats THEN StatIncr[statOisDiscarded]; DriverDefs.PutOnGlobalDoneQueue[b]; -- done with this packet RETURN; END; IF (badChecksum _ IF checkIt THEN NOT Checksums.TestChecksum[b] ELSE FALSE) THEN <> BEGIN IF CommFlags.doStats THEN BEGIN StatIncr[statReceivedBadOisChecksum]; StatIncr[statOisDiscarded]; END; DriverDefs.PutOnGlobalDoneQueue[b]; -- done with this packet RETURN; END; <> IF CommFlags.doStorms AND stormy AND PacketHit[] THEN BEGIN DriverDefs.PutOnGlobalDoneQueue[b]; RETURN; END; -- for debugging only incomingNet _ b.network; IF destHost = myHostID OR ((broadcastPacket_(destHost = allHostIDs)) AND (incomingNet.netNumber = b.ois.destination.net) OR (b.ois.destination.net = NSAddress.nullNetworkNumber)) THEN BEGIN -- incomming packet for us (we may have broadcast it) IF NOT DeliveredToLocalSocket[b, FALSE] THEN < do not copy this buffer, but deliver it>> BEGIN <> IF b.ois.destination.socket = OISCPConstants.routingInformationSocket THEN Router.RoutingInformationPacket[b] -- we still own this packet! ELSE BEGIN -- packet for unknown socket IF NOT broadcastPacket THEN BEGIN SendErrorPacket[b, noSocketOisErrorCode, 0]; IF CommFlags.doStats THEN StatIncr[statJunkOisForUsNoLocalSocket]; END ELSE IF CommFlags.doStats THEN StatIncr[statJunkBroadcastOis] END; DriverDefs.PutOnGlobalDoneQueue[b]; -- done with this packet END; END ELSE SELECT TRUE FROM routersFunction=interNetworkRouting => BEGIN Router.ForwardPacket[b]; -- dispatcher returns to system pool END; b.ois.destination.socket=OISCPConstants.routingInformationSocket => BEGIN Router.RoutingInformationPacket[b]; -- we still own this packet! DriverDefs.PutOnGlobalDoneQueue[b]; END; ENDCASE => BEGIN IF CommFlags.doStats THEN StatIncr[statOisDiscarded]; DriverDefs.PutOnGlobalDoneQueue[b]; -- we got the packet when we shouldn't have! END; END; -- ReceivePacket <> <> <> PacketHit: ENTRY PROCEDURE RETURNS [BOOLEAN] = BEGIN IF (lightning _ lightning + 1) > bolt OR lightning < 0 THEN BEGIN IF lightning > bolt THEN BEGIN IF bolt > 100 THEN BEGIN randLong: LONG CARDINAL _ ProcessorFace.GetClockPulses[]; rand: CARDINAL _ LOOPHOLE[randLong, Basics.LongNumber].lowbits; lightning _ -INTEGER[rand MOD 20B]; bolt _ 10; END ELSE BEGIN lightning _ 0; bolt _ bolt + 1; END; END; IF CommFlags.doStats THEN StatIncr[statZappedP]; RETURN[TRUE]; END ELSE RETURN[FALSE]; END; -- PacketHit <> <> <> DeliveredToLocalSocket: ENTRY PROCEDURE [b: BufferDefs.OisBuffer, useCopy: BOOLEAN] RETURNS [BOOLEAN] = BEGIN ENABLE UNWIND => NULL; destSocket: NSAddress.SocketNumber _ b.ois.destination.socket; sH, prevSH: SocketHandle; <> FOR sH _ (prevSH _ socketTable.first), sH.next UNTIL sH = NIL DO IF sH.localAddr.socket = destSocket THEN BEGIN IF useCopy THEN EnqueueCopyOfNewInput[sH, b] ELSE EnqueueNewInput[sH, b]; <> <> IF prevSH # socketTable.first THEN BEGIN prevSH.next _ sH.next; -- this removes sH from the list sH.next _ socketTable.first; socketTable.first _ sH; -- this puts sH at head of list END; RETURN[TRUE]; END; prevSH _ sH; ENDLOOP; RETURN[FALSE]; END; -- DeliveredToLocalSocket <> <> <> EnqueueNewInput: INTERNAL PROCEDURE [sH: SocketHandle, b: BufferDefs.OisBuffer] = INLINE BEGIN IF (sH.channelState = aborted) OR NOT (OISCP.CreditReceiveOisBuffer[sH.pool, b]) THEN BEGIN IF CommFlags.doStats THEN StatsDefs.StatIncr[statOisInputQueueOverflow]; DriverDefs.PutOnGlobalDoneQueue[b]; RETURN; END; b.status _ LOOPHOLE[Router.XmitStatus[goodCompletion]]; EnqueueOis[sH.completedUserGetQueue, b]; BROADCAST sH.newUserInput; END; -- EnqueueNewInput <> <> <> EnqueueCopyOfNewInput: INTERNAL PROCEDURE [ sH: SocketHandle, b: BufferDefs.OisBuffer] = INLINE BEGIN getBuffer: BufferDefs.OisBuffer _ IF sH.channelState = aborted THEN NIL ELSE MaybeGetFreeReceiveOisBufferFromPool[sH.pool]; <> IF (getBuffer # NIL) THEN BEGIN getBuffer.status _ LOOPHOLE[Router.XmitStatus[goodCompletion]]; <> <> CommUtilDefs.CopyLong[ from: @b.ois.checksum, nwords: (b.ois.pktLength + 1)/2, to: @getBuffer.ois.checksum]; EnqueueOis[sH.completedUserGetQueue, getBuffer]; BROADCAST sH.newUserInput; END ELSE IF CommFlags.doStats THEN StatsDefs.StatIncr[statOisInputQueueOverflow]; <> END; -- EnqueueNewLocalInput <> BroadcastThisPacket: PUBLIC PROCEDURE [b: BufferDefs.OisBuffer] = BEGIN network: Network; IF CommFlags.doStats THEN StatIncr[statOisBroadcast]; b.allNets _ TRUE; -- this is where it gets turned on b.ois.destination.host _ NSAddress.broadcastHostNumber; b.network _ network _ DriverDefs.GetDeviceChain[]; IF network = NIL THEN BEGIN DriverDefs.PutOnGlobalDoneQueue[b]; IF CommFlags.doStats THEN StatsDefs.StatIncr[statOisSentNowhere]; RETURN; END; SendBroadcastPacketToCorrectNet[b]; END; -- BroadcastThisPacket <> SendBroadcastPacketToCorrectNet: PUBLIC PROCEDURE [b: BufferDefs.OisBuffer] = BEGIN network: Network _ b.network; IF ~network.alive OR (b.bypassZeroNet AND network.netNumber = [0, 0]) THEN BEGIN DriverDefs.PutOnGlobalDoneQueue[b]; RETURN; END; <> b.ois.destination.net _ b.ois.source.net _ network.netNumber; b.ois.source.host _ myHostID; IF checkIt THEN Checksums.SetChecksum[b] ELSE b.ois.checksum _ 177777B; LOOPHOLE[b.status, DriverDefs.DriverXmitStatus] _ goodCompletion; network.encapsulateOis[b, NSAddress.broadcastHostNumber]; network.sendBuffer[b]; END; -- SendBroadcastPacketToCorrectNet <> <> <> SendErrorPacket: PUBLIC PROCEDURE [offendingPkt: BufferDefs.OisBuffer, errCode: OISCPTypes.OISErrorCode, errParm: CARDINAL] = BEGIN net: Network = offendingPkt.network; b: BufferDefs.OisBuffer; offenseLen: CARDINAL; IF offendingPkt.ois.transCntlAndPktTp.packetType=error THEN RETURN; -- don't send errors about errors IF (b _ DriverDefs.MaybeGetFreeOisBuffer[])=NIL THEN RETURN; -- give up! b.ois.destination _ offendingPkt.ois.source; b.ois.source _ [ IF net=NIL THEN OISCP.unknownNetID ELSE net.netNumber, myHostID, OISCP.unknownSocketID]; b.ois.transCntlAndPktTp _ [initialTransportControl, error]; b.ois.errorType _ errCode; b.ois.errorParameter _ errParm; offenseLen _ MIN[offendingPkt.ois.pktLength, OISCPTypes.bytesPerPktText-4]; -- four is for errorType and errorParameter. CommUtilDefs.CopyLong[@offendingPkt.ois, (offenseLen+1)/2, @b.ois.errorBody]; SetOisPacketTextLength[b, offenseLen+4]; SendPacket[b]; END; -- SendErrorPacket <> <> <> <> OisRouterOn: PUBLIC PROCEDURE = BEGIN OisRouterActivate[]; Router.RoutingTableOn[]; DriverDefs.SetOisRouter[@oiscpRouter]; END; -- OisRouterOn OisRouterActivate: ENTRY PROCEDURE = INLINE BEGIN myHostID _ NSAddress.GetProcessorID[]; IF primaryMDS THEN socketTable _ [length: 0, first: NIL]; END; -- OisRouterActivate OisRouterOff: PUBLIC PROCEDURE = BEGIN DriverDefs.SetOisRouter[NIL]; OisRouterDeactivate[]; Router.RoutingTableOff[]; END; -- OisRouterOff OisRouterDeactivate: ENTRY PROCEDURE = INLINE BEGIN <> <> END; -- OisRouterDeactivate <> <> IF primaryMDS THEN spareSocketID _ initialSpareSocketID; END. -- RouterImpl module. LOG Time: January 19, 1980 4:05 PM By: Dalal Action: Split OISCPRouter into two. Time: January 21, 1980 6:07 PM By: Dalal Action: one lock for SocketImpl and RouterImpl. Time: March 13, 1980 4:55 PM By: BLyon Action: modified SendPacket. Time: March 18, 1980 4:09 PM By: BLyon Action: Modified EnqueueNewInput where it gets an input buffer. Time: May 12, 1980 6:38 PM By: BLyon Action: Put checksum into microcode (switched order parameters too). Time: May 16, 1980 10:07 AM PM By: BLyon Action: Removed all ShortenPointer to allow multiple MDS. Time: June 30, 1980 1:02 PM By: BLyon Action: Checkit init to FALSE instead of TRUE.. Time: July 22, 1980 11:03 AM By: BLyon Action: Checkit changed back to TRUE; checksums stuff put in seperate modules; we now receive out own broadcasts. Time: August 1, 1980 1:29 PM By: BLyon Action: replaced internetRouter by routersFunction. Time: September 13, 1980 6:15 PM By: HGM Action: Add StateChanged. Time: September 18, 1980 3:34 PM By: BLyon Action: AssignOisAddress puts unknownNetID in network field rather than primaryNetID. Time: February 24, 1981 3:25 PM By: BLyon Action: put extra clause in ReceivePacket so that an INR would forward a broadcast instead of eating it with a local socket.