-- 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.