-- Copyright (C) 1984, 1985 by Xerox Corporation. All rights reserved. -- GateStats.mesa, HGM, 23-Oct-85 23:19:09 DIRECTORY Environment USING [Byte], Inline USING [LowHalf], Process USING [Detach], System USING [localHostNumber, nullHostNumber], Buffer USING [ReturnBuffer], CpuIdle USING [GetCalibration, GetCycles], Driver USING [Network, GetDeviceChain], EthernetFormat USING [EtherStatsEntry, ethernetStatsReply, etherVersion], EthernetDriverFriends USING [EtherStatsInfo], GateControlDefs USING [pupStatsAck, pupStatsNak, pupStatsSend], PhoneNetFriends USING [PhoneNetInfo, StatsPtrToStats], Protocol1 USING [GetContext], PupDefs USING [ PupBuffer, GetPupContentsBytes, PupRouterSendThis, SwapPupSourceAndDest, ReturnPup, PupSocket, PupSocketMake, SetPupContentsWords, veryLongWait], PupRouterDefs USING [NetworkContext], PupTypes USING [statSoc, fillInPupAddress], PupWireFormat USING [MesaToBcplLongNumber], SlaFormat USING [LineState, SlaStatsEntry, slaStatsReply, slaVersion]; GateStats: PROGRAM IMPORTS Inline, Process, System, Buffer, CpuIdle, Driver, Protocol1, PhoneNetFriends, PupDefs, PupWireFormat EXPORTS Buffer, GateControlDefs = BEGIN Network: PUBLIC TYPE = Driver.Network; soc: PupDefs.PupSocket; GateStatsOn: PUBLIC PROCEDURE = BEGIN Process.Detach[FORK Stats[]]; END; Stats: PROCEDURE = BEGIN b: PupDefs.PupBuffer; firstNetwork: Driver.Network = Driver.GetDeviceChain[]; soc ← PupDefs.PupSocketMake[ PupTypes.statSoc, PupTypes.fillInPupAddress, PupDefs.veryLongWait]; DO -- forever IF (b ← soc.get[]) # NIL THEN BEGIN SELECT b.pup.pupType FROM GateControlDefs.pupStatsSend => BEGIN target: CARDINAL = b.pup.pupWords[0]; bytes: CARDINAL = PupDefs.GetPupContentsBytes[b]; IF bytes < 2 THEN GOTO Ignore; FOR network: Driver.Network ← firstNetwork, network.next UNTIL network = NIL DO context: PupRouterDefs.NetworkContext ← Protocol1.GetContext[network, pup]; IF context.pupNetNumber # target THEN LOOP; IF network.stats = NIL THEN GOTO Reject; SELECT bytes FROM 2 => OldPupStats[b, network]; 4 => NewPupStats[b, network]; ENDCASE => GOTO Ignore; b.pup.pupType ← GateControlDefs.pupStatsAck; PupDefs.SwapPupSourceAndDest[b]; PupDefs.PupRouterSendThis[b]; GOTO Sent; ENDLOOP; GOTO Ignore; END; ENDCASE => GOTO Ignore; EXITS Reject => BEGIN PupDefs.ReturnPup[b, GateControlDefs.pupStatsNak, 0]; END; Ignore => BEGIN Buffer.ReturnBuffer[b]; END; Sent => NULL; END; ENDLOOP; END; NewPupStats: PROCEDURE [b: PupDefs.PupBuffer, network: Driver.Network] = BEGIN SELECT network.device FROM ethernet, ethernetOne => NewEthernetStats[b, network]; phonenet => NewPhoneStats[b, network]; ENDCASE => ERROR; END; Cpu: TYPE = RECORD [cycles, cyclesPerSecond: LONG CARDINAL]; NewEthernetStats: PUBLIC PROCEDURE [b: PupDefs.PupBuffer, network: Driver.Network] = BEGIN stats: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo ← network.stats; cpu: LONG POINTER TO Cpu = LOOPHOLE[@b.pup.pupWords[2]]; esi: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo = LOOPHOLE[cpu + SIZE[Cpu]]; b.pup.pupWords[0] ← EthernetFormat.ethernetStatsReply; b.pup.pupWords[1] ← EthernetFormat.etherVersion+1; cpu↑ ← [ cycles: CpuIdle.GetCycles[], cyclesPerSecond: CpuIdle.GetCalibration[].cyclesPerSecond]; esi↑ ← stats↑; PupDefs.SetPupContentsWords[b, 2 + SIZE[Cpu] + SIZE[EthernetDriverFriends.EtherStatsInfo]]; END; NewPhoneStats: PUBLIC PROCEDURE [b: PupDefs.PupBuffer, network: Driver.Network] = BEGIN stats: PhoneNetFriends.PhoneNetInfo = PhoneNetFriends.StatsPtrToStats[network.stats]; cpu: LONG POINTER TO Cpu = LOOPHOLE[@b.pup.pupWords[2]]; psi: LONG POINTER TO PhoneNetFriends.PhoneNetInfo = LOOPHOLE[cpu + SIZE[Cpu]]; b.pup.pupWords[0] ← SlaFormat.slaStatsReply; b.pup.pupWords[1] ← SlaFormat.slaVersion+1; cpu↑ ← [ cycles: CpuIdle.GetCycles[], cyclesPerSecond: CpuIdle.GetCalibration[].cyclesPerSecond]; psi↑ ← stats; PupDefs.SetPupContentsWords[b, 2 + SIZE[Cpu] + SIZE[PhoneNetFriends.PhoneNetInfo]]; END; OldPupStats: PROCEDURE [b: PupDefs.PupBuffer, network: Driver.Network] = BEGIN SELECT network.device FROM ethernet, ethernetOne => OldEthernetStats[b, network]; phonenet => OldPhoneStats[b, network]; ENDCASE => ERROR; END; OldEthernetStats: PUBLIC PROCEDURE [b: PupDefs.PupBuffer, network: Driver.Network] = BEGIN ese: LONG POINTER TO EthernetFormat.EtherStatsEntry; esi: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo ← network.stats; 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]; PupDefs.SetPupContentsWords[b, 1 + SIZE[EthernetFormat.EtherStatsEntry]]; END; OldPhoneStats: PUBLIC PROCEDURE [b: PupDefs.PupBuffer, network: Driver.Network] = 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; stats: PhoneNetFriends.PhoneNetInfo = PhoneNetFriends.StatsPtrToStats[network.stats]; 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]); END; GateStatsOn[]; END.