-- Copyright (C) 1984, 1985 by Xerox Corporation. All rights reserved. -- GateStats.mesa, HGM, 7-Jan-85 22:36:30 DIRECTORY Environment USING [Byte], Inline USING [LowHalf], Process USING [Detach], System USING [localHostNumber, nullHostNumber], Buffer USING [ReturnBuffer], Driver USING [Network, GetDeviceChain], EthernetFormat USING [EtherStatsEntry, ethernetStatsReply, etherVersion], EthernetDriverFriends USING [EtherStatsInfo], GateControlDefs USING [pupStatsAck, pupStatsNak, pupStatsSend], PhoneNetFriends USING [PhoneNetInfo], PupDefs USING [ PupBuffer, GetPupContentsBytes, PupRouterSendThis, SwapPupSourceAndDest, ReturnPup, PupSocket, PupSocketMake, SetPupContentsWords, veryLongWait], PupTypes USING [statSoc, fillInPupAddress], PupWireFormat USING [MesaToBcplLongNumber], SlaFormat USING [LineState, SlaStatsEntry, slaStatsReply, slaVersion]; GateStats: PROGRAM IMPORTS Inline, Process, System, Buffer, PupWireFormat, PupDefs, Driver EXPORTS GateControlDefs = BEGIN OPEN PupDefs; soc: PupSocket; GateStatsOn: PUBLIC PROCEDURE = BEGIN Process.Detach[FORK Stats[]]; END; Stats: PROCEDURE = BEGIN b: PupBuffer; firstNetwork: Driver.Network = Driver.GetDeviceChain[]; SetupStatsEntries[]; soc ← PupSocketMake[ PupTypes.statSoc, PupTypes.fillInPupAddress, veryLongWait]; DO -- forever IF (b ← soc.get[]) # NIL THEN BEGIN SELECT b.pup.pupType FROM GateControlDefs.pupStatsSend => BEGIN target: CARDINAL = b.pup.pupWords[0]; network: Driver.Network; IF GetPupContentsBytes[b] # 2 THEN GOTO Ignore; FOR network ← firstNetwork, network.next UNTIL network = NIL DO IF network.pupNetNumber # target THEN LOOP; IF network.pupStats = NIL OR network.statsLevel0 = NIL THEN GOTO Reject; IF network.pupStats[b, network] THEN GOTO Send; GOTO Reject; ENDLOOP; GOTO Ignore; END; ENDCASE => GOTO Ignore; EXITS Send => BEGIN -- pupLength setup already b.pup.pupType ← GateControlDefs.pupStatsAck; SwapPupSourceAndDest[b]; PupRouterSendThis[b]; END; Reject => BEGIN ReturnPup[b, GateControlDefs.pupStatsNak, 0]; END; Ignore => BEGIN Buffer.ReturnBuffer[b]; END; END; ENDLOOP; END; SetupStatsEntries: PUBLIC PROCEDURE = BEGIN network: Driver.Network; FOR network ← Driver.GetDeviceChain[], network.next UNTIL network = NIL DO SELECT network.device FROM ethernet, ethernetOne => network.pupStats ← EthernetStats; phonenet => network.pupStats ← PhoneStats; ENDCASE; ENDLOOP; END; EthernetStats: PUBLIC PROCEDURE [b: PupBuffer, network: Driver.Network] RETURNS [BOOLEAN] = BEGIN ese: LONG POINTER TO EthernetFormat.EtherStatsEntry; esi: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo ← network.statsLevel0; b.pup.pupWords[0] ← EthernetFormat.ethernetStatsReply; ese ← LOOPHOLE[@b.pup.pupWords[1]]; ese↑ ← [ version: EthernetFormat.etherVersion, packetsSent: PupWireFormat.MesaToBcplLongNumber[esi.packetsSent], badSendStatus: PupWireFormat.MesaToBcplLongNumber[esi.badSendStatus], overruns: PupWireFormat.MesaToBcplLongNumber[esi.overrun + esi.underrun], packetsRecv: PupWireFormat.MesaToBcplLongNumber[esi.packetsRecv], badRecvStatus: PupWireFormat.MesaToBcplLongNumber[esi.badRecvStatus], inputOff: PupWireFormat.MesaToBcplLongNumber[esi.packetsMissed], loadTable:]; FOR i: CARDINAL IN [0..16) DO ese.loadTable[i] ← PupWireFormat.MesaToBcplLongNumber[esi.loadTable[i]]; ENDLOOP; ese.loadTable[16] ← PupWireFormat.MesaToBcplLongNumber[esi.tooManyCollisions]; SetPupContentsWords[b, 1 + SIZE[EthernetFormat.EtherStatsEntry]]; RETURN[TRUE]; END; PhoneStats: PUBLIC PROCEDURE [b: PupBuffer, network: Driver.Network] RETURNS [BOOLEAN] = BEGIN state: SlaFormat.LineState; RoutingTableEntry: TYPE = RECORD [hops, line: Environment.Byte]; activeLines: CARDINAL = 1; maxSlaHost: CARDINAL = 1; sizeOfRoutingTable: CARDINAL = maxSlaHost*SIZE[RoutingTableEntry]; rte: LONG POINTER TO RoutingTableEntry; sse: LONG POINTER TO SlaFormat.SlaStatsEntry; CrapForINRLoophole: TYPE = MONITORED RECORD [ clientData: LONG UNSPECIFIED, lineNumber: CARDINAL]; foo: LONG POINTER TO CrapForINRLoophole = network.statsLevel0; stats: LONG POINTER TO PhoneNetFriends.PhoneNetInfo = foo.clientData; SELECT TRUE FROM stats.remoteHostNumber = System.nullHostNumber => state ← down; stats.remoteHostNumber = System.localHostNumber => state ← loopedBack; ENDCASE => state ← up; b.pup.pupWords[0] ← SlaFormat.slaStatsReply; b.pup.pupWords[1] ← SlaFormat.slaVersion; b.pup.pupWords[2] ← maxSlaHost; rte ← LOOPHOLE[@b.pup.pupWords[3]]; rte↑ ← [0, 0]; b.pup.pupWords[3 + sizeOfRoutingTable] ← activeLines - 1; sse ← LOOPHOLE[@b.pup.pupWords[4 + sizeOfRoutingTable]]; sse↑ ← [ packetsSent: PupWireFormat.MesaToBcplLongNumber[stats.stats[pktsSent]], packetsRecv: PupWireFormat.MesaToBcplLongNumber[stats.stats[pktsReceived]], bytesSent: PupWireFormat.MesaToBcplLongNumber[stats.stats[bytesSent]], bytesRecv: PupWireFormat.MesaToBcplLongNumber[stats.stats[bytesReceived]], syncErrors: Inline.LowHalf[stats.stats[rcvErrorNoGet] + stats.stats[rcvErrorDataLost]], badCrc: Inline.LowHalf[stats.stats[rcvErrorCRC]], controlError: Inline.LowHalf[stats.stats[rcvDeviceError]], state: state]; b.pup.pupLength ← 22 + 2*(4 + sizeOfRoutingTable + activeLines*SIZE[SlaFormat.SlaStatsEntry]); RETURN[TRUE]; END; GateStatsOn[]; END.