-- File: GateStats.mesa - last edit: -- AOF 4-Feb-88 12:39:20 -- HGM 23-Oct-85 23:19:09 -- Copyright (C) 1984, 1985, 1988 by Xerox Corporation. All rights reserved. DIRECTORY Buffer USING [], Environment USING [Byte], Inline USING [LowHalf], Process USING [Detach], CpuIdle USING [GetCalibration, GetCycles], Driver USING [Device, GetDeviceChain], EthernetFormat USING [EtherStatsEntry, ethernetStatsReply, etherVersion], EthernetDriverFriends USING [EtherStatsInfo], GateControlDefs USING [pupStatsAck, pupStatsNak, pupStatsSend], Protocol1 USING [GetContext], PupDefs USING [ PupBuffer, GetPupContentsBytes, PupRouterSendThis, SwapPupSourceAndDest, ReturnPup, PupSocket, PupSocketMake, SetPupContentsWords, veryLongWait, ReturnBuffer, Body], PupRouterDefs USING [NetworkContext], PupTypes USING [statSoc, fillInPupAddress], PupWireFormat USING [MesaToBcplLongNumber], SlaFormat USING [LineState, SlaStatsEntry, slaStatsReply, slaVersion], SptpOps USING [GetProtocolInfo, StatsRecord], SptpProtocol USING [ProtocolObject]; GateStats: PROGRAM IMPORTS Inline, Process, CpuIdle, Driver, Protocol1, PupDefs, PupWireFormat, SptpOps EXPORTS Buffer, GateControlDefs = BEGIN Device: PUBLIC <<Buffer>> TYPE = Driver.Device; soc: PupDefs.PupSocket; GateStatsOn: PUBLIC PROCEDURE = BEGIN Process.Detach[FORK Stats[]]; END; Stats: PROCEDURE = BEGIN b: PupDefs.PupBuffer; firstNetwork: Device = Driver.GetDeviceChain[]; soc ← PupDefs.PupSocketMake[ PupTypes.statSoc, PupTypes.fillInPupAddress, PupDefs.veryLongWait]; DO -- forever IF (b ← soc.get[]) # NIL THEN BEGIN body: PupDefs.Body ← b.pup; SELECT body.pupType FROM GateControlDefs.pupStatsSend => BEGIN target: CARDINAL = body.pupWords[0]; bytes: CARDINAL = PupDefs.GetPupContentsBytes[b]; IF bytes < 2 THEN GOTO Ignore; FOR network: Device ← 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; body.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 PupDefs.ReturnBuffer[b]; END; Sent => NULL; END; ENDLOOP; END; NewPupStats: PROCEDURE [b: PupDefs.PupBuffer, network: Device] = 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: Device] = BEGIN body: PupDefs.Body ← b.pup; stats: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo ← network.stats; cpu: LONG POINTER TO Cpu = LOOPHOLE[@body.pupWords[2]]; esi: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo = LOOPHOLE[cpu + SIZE[Cpu]]; body.pupWords[0] ← EthernetFormat.ethernetStatsReply; body.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: Device] = BEGIN body: PupDefs.Body ← b.pup; stats: LONG POINTER TO SptpOps.StatsRecord = network.stats; cpu: LONG POINTER TO Cpu = LOOPHOLE[@body.pupWords[2]]; psi: LONG POINTER TO SptpOps.StatsRecord = LOOPHOLE[cpu + SIZE[Cpu]]; body.pupWords[0] ← SlaFormat.slaStatsReply; body.pupWords[1] ← SlaFormat.slaVersion+1; cpu↑ ← [ cycles: CpuIdle.GetCycles[], cyclesPerSecond: CpuIdle.GetCalibration[].cyclesPerSecond]; psi↑ ← stats↑; PupDefs.SetPupContentsWords[ b, 2 + SIZE[Cpu] + SIZE[SptpOps.StatsRecord]]; END; OldPupStats: PROCEDURE [b: PupDefs.PupBuffer, network: Device] = BEGIN SELECT network.device FROM ethernet, ethernetOne => OldEthernetStats[b, network]; phonenet => OldPhoneStats[b, network]; ENDCASE => ERROR; END; OldEthernetStats: PUBLIC PROCEDURE [b: PupDefs.PupBuffer, network: Device] = BEGIN body: PupDefs.Body ← b.pup; ese: LONG POINTER TO EthernetFormat.EtherStatsEntry; esi: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo ← network.stats; body.pupWords[0] ← EthernetFormat.ethernetStatsReply; ese ← LOOPHOLE[@body.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: Device] = BEGIN maxSlaHost: CARDINAL = 1; activeLines: CARDINAL = 1; state: SlaFormat.LineState; body: PupDefs.Body ← b.pup; info: SptpProtocol.ProtocolObject; rte: LONG POINTER TO RoutingTableEntry; sse: LONG POINTER TO SlaFormat.SlaStatsEntry; RoutingTableEntry: TYPE = RECORD [hops, line: Environment.Byte]; sizeOfRoutingTable: CARDINAL = maxSlaHost*SIZE[RoutingTableEntry]; stats: LONG POINTER TO SptpOps.StatsRecord = network.stats; SptpOps.GetProtocolInfo[network, @info]; state ← SELECT TRUE FROM info.state # data => state ← down, info.him = info.me => state ← loopedBack, ENDCASE => state ← up; body.pupWords[0] ← SlaFormat.slaStatsReply; body.pupWords[1] ← SlaFormat.slaVersion; body.pupWords[2] ← maxSlaHost; rte ← LOOPHOLE[@body.pupWords[3]]; rte↑ ← [0, 0]; body.pupWords[3 + sizeOfRoutingTable] ← activeLines - 1; sse ← LOOPHOLE[@body.pupWords[4 + sizeOfRoutingTable]]; sse↑ ← [ packetsSent: PupWireFormat.MesaToBcplLongNumber[stats.packetsSent], packetsRecv: PupWireFormat.MesaToBcplLongNumber[stats.pktsReceived], bytesSent: PupWireFormat.MesaToBcplLongNumber[stats.bytesSent], bytesRecv: PupWireFormat.MesaToBcplLongNumber[stats.bytesReceived], syncErrors: Inline.LowHalf[stats.dataLost], badCrc: Inline.LowHalf[stats.checksumError], controlError: Inline.LowHalf[stats.deviceError], state: state]; body.pupLength ← 22 + 2*(4 + sizeOfRoutingTable + activeLines*SIZE[SlaFormat.SlaStatsEntry]); END; GateStatsOn[]; END.