-- Copyright (C) 1984, 1985 by Xerox Corporation. All rights reserved. -- DeviceInfo.mesa, HGM, 10-Jun-85 22:11:05 DIRECTORY Format USING [], -- needed by Put.Date and friends Heap USING [systemZone], Menu USING [ItemObject, MCRType, Create, Instantiate], Process USING [Yield], Put USING [ CR, Char, Date, HostNumber, Line, LongDecimal, LongNumber, NetworkNumber, Number, Text], String USING [AppendChar, AppendNumber, AppendString], System USING [HostNumber, localHostNumber, NetworkNumber, nullHostNumber], Time USING [Current], UserInput USING [GetDefaultWindow], Window USING [Handle], EthernetDriverFriends USING [EtherStatsInfo], PhoneNetFriends USING [PhoneNetInfo], PhoneNetExtras USING [ leafBytesSend, leafDupsFiltered, leafPktsSend, nsBytesSend, nsCongestion, nsDupsFiltered, nsTooGreedy, pupBytesSend, pupCongestion, pupDupsFiltered, pupTooGreedy], Sla USING [ DriverStatistics, LineInfo, longHop, noPartner, RoutingTableEntry, SlaHost], Driver USING [GetDeviceChain, Network]; DeviceInfo: PROGRAM IMPORTS Heap, Menu, Process, Put, String, System, Time, UserInput, Driver = BEGIN z: UNCOUNTED ZONE = Heap.systemZone; DoMenu: Menu.MCRType = BEGIN firstNetwork: Driver.Network ← Driver.GetDeviceChain[]; device: CARDINAL ← 0; FOR network: Driver.Network ← firstNetwork, network.next UNTIL network = NIL DO IF index = device THEN BEGIN SELECT network.device FROM ethernet, ethernetOne => ShowEthernet[NIL, network]; sla => ShowSla[NIL, network]; phonenet => ShowPhoneNet[NIL, network]; ENDCASE => ERROR; RETURN; END; device ← device + 1; ENDLOOP; END; ShowEthernet: PROCEDURE [wh: Window.Handle, network: Driver.Network] = BEGIN stats: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo ← network.statsLevel0; PrintHeader[wh, "Ethernet"L, FALSE]; IF network.device = ethernetOne THEN Put.Text[wh, "One"L]; Put.Text[wh, " Statistics for "L]; Put.Number[wh, network.pupNetNumber, [8, FALSE, TRUE, 0]]; Put.Text[wh, "#"L]; Put.Number[wh, network.pupHostNumber, [8, FALSE, TRUE, 0]]; Put.Text[wh, "#, NS net "L]; PutNetNumbers[wh, network.netNumber]; Put.CR[wh]; IF stats = NIL THEN RETURN; Put.Text[wh, "Rcv: pkts "L]; Put.LongDecimal[wh, stats.packetsRecv]; Put.Text[wh, ", words "L]; Put.LongDecimal[wh, stats.wordsRecv]; Put.Text[wh, ", bad "L]; Put.LongDecimal[wh, stats.badRecvStatus]; Put.Text[wh, ", missed "L]; Put.LongDecimal[wh, stats.packetsMissed]; Put.CR[wh]; IF stats.badRecvStatus # 0 OR stats.okButDribble # 0 THEN BEGIN Put.Text[wh, " crc "L]; Put.LongDecimal[wh, stats.badCrc]; Put.Text[wh, ", bad alignment but ok crc "L]; Put.LongDecimal[wh, stats.badAlignmentButOkCrc]; Put.Text[wh, ", crc and bad alignment "L]; Put.LongDecimal[wh, stats.crcAndBadAlignment]; Put.CR[wh]; Put.Text[wh, " ok but dribble "L]; Put.LongDecimal[wh, stats.okButDribble]; Put.Text[wh, ", too long "L]; Put.LongDecimal[wh, stats.packetTooLong]; Put.Text[wh, ", overrun "L]; Put.LongDecimal[wh, stats.overrun]; Put.Text[wh, ", idle "L]; Put.LongDecimal[wh, stats.idleInput]; Put.CR[wh]; END; Put.Text[wh, "Xmit: pkts "L]; Put.LongDecimal[wh, stats.packetsSent]; Put.Text[wh, ", words "L]; Put.LongDecimal[wh, stats.wordsSent]; Put.Text[wh, ", bad "L]; Put.LongDecimal[wh, stats.badSendStatus]; Put.CR[wh]; IF stats.badSendStatus # 0 OR stats.tooManyCollisions # 0 THEN BEGIN Put.Text[wh, " underrun "L]; Put.LongDecimal[wh, stats.underrun]; Put.Text[wh, ", stuck "L]; Put.LongDecimal[wh, stats.stuckOutput]; Put.Text[wh, ", too many collisions "L]; Put.LongDecimal[wh, stats.tooManyCollisions]; Put.CR[wh]; END; Put.Text[wh, "Lds:"L]; FOR i: CARDINAL IN [0..16) DO Put.Char[wh, ' ]; Put.LongDecimal[wh, stats.loadTable[i]]; ENDLOOP; Put.CR[wh]; END; ShowSla: PROCEDURE [wh: Window.Handle, network: Driver.Network] = BEGIN OPEN Sla; stats: LONG POINTER TO DriverStatistics ← network.statsLevel0; lineInfo: LONG POINTER TO ARRAY [0..0) OF LineInfo ← stats.info; routingTable: LONG POINTER TO ARRAY SlaHost OF RoutingTableEntry ← stats.routingTable; PrintHeader[wh, "SLA Statistics for "L, FALSE]; Put.Number[wh, network.pupNetNumber, [8, FALSE, TRUE, 0]]; Put.Text[wh, "#"L]; Put.Number[wh, network.pupHostNumber, [8, FALSE, TRUE, 0]]; Put.Text[wh, "#, NS net "L]; PutNetNumbers[wh, network.netNumber]; Put.CR[wh]; BEGIN LD6: PROCEDURE [n: LONG CARDINAL] = BEGIN Put.LongNumber[wh, n, [10, FALSE, TRUE, 6]]; END; LD8: PROCEDURE [n: LONG CARDINAL] = BEGIN Put.LongNumber[wh, n, [10, FALSE, TRUE, 8]]; END; LD12: PROCEDURE [n: LONG CARDINAL] = BEGIN Put.LongNumber[wh, n, [10, FALSE, TRUE, 12]]; END; Put.Line[ wh, " ---Packets--- --------Bytes------- -------Errors------- Ln To Sent Recv Sent Recv Ov CRC Sync Cntrl Send Recv State"L]; FOR line: CARDINAL IN [0..stats.lines) DO info: LONG POINTER TO LineInfo ← @lineInfo[line]; Put.Number[wh, line, [8, FALSE, TRUE, 2]]; IF info.partner = noPartner THEN Put.Text[wh, " ?"L] ELSE Put.Number[wh, info.partner, [8, FALSE, TRUE, 3]]; LD8[info.packetsSent]; LD8[info.packetsRecv]; LD12[info.bytesSent]; LD12[info.bytesRecv]; LD6[info.overrun]; LD6[info.crcErrors]; LD6[info.syncErrors]; LD6[info.controlErrors]; LD6[info.sendErrors]; LD6[info.recvErrors]; Put.Text[wh, " "L]; SELECT info.state FROM down => Put.Line[wh, "Down"L]; loopedBack => Put.Line[wh, "Looped"L]; halfUp => Put.Line[wh, "Half Up"L]; up => Put.Line[wh, "Up"L]; ENDCASE => Put.Line[wh, " ??"L]; IF info.deaths # 0 OR info.stuck # 0 OR info.timeout # 0 OR info.garbagePackets # 0 THEN BEGIN Put.Text[wh, "Deaths: "L]; Put.LongDecimal[wh, info.deaths]; Put.Text[wh, ", Send Stuck: "L]; Put.LongDecimal[wh, info.stuck]; Put.Text[wh, ", Recv Timeout: "L]; Put.LongDecimal[wh, info.timeout]; Put.Text[wh, ", GarbagePackets: "L]; Put.LongDecimal[wh, info.garbagePackets]; Put.Line[wh, "."L]; END; DoSomeYields[]; ENDLOOP; END; BEGIN O4: PROCEDURE [n: CARDINAL] = BEGIN Put.Number[wh, n, [8, FALSE, TRUE, 4]]; END; D5: PROCEDURE [n: CARDINAL] = BEGIN Put.Number[wh, n, [10, FALSE, TRUE, 5]]; END; k: CARDINAL ← 0; Put.Line[wh, "SLA Routing Table:"L]; FOR host: SlaHost IN SlaHost DO rte: LONG POINTER TO RoutingTableEntry = @routingTable[host]; IF rte.hops = longHop THEN LOOP; IF k # 0 THEN Put.Text[wh, " "L]; O4[host]; D5[rte.line]; D5[rte.hops]; IF (k ← k + 1) = 4 THEN BEGIN Put.CR[wh]; k ← 0; END; ENDLOOP; IF k # 0 THEN Put.CR[wh]; END; END; ShowPhoneNet: PROCEDURE [wh: Window.Handle, network: Driver.Network] = BEGIN CrapForINRLoophole: TYPE = MONITORED RECORD [ clientData: LONG UNSPECIFIED, lineNumber: CARDINAL]; foo: LONG POINTER TO CrapForINRLoophole = network.statsLevel0; stats: LONG POINTER TO PhoneNetFriends.PhoneNetInfo ← foo.clientData; PrintHeader[wh, "PhoneNet"L, FALSE]; Put.Text[wh, " Statistics for "L]; Put.Number[wh, network.pupNetNumber, [8, FALSE, TRUE, 0]]; Put.Text[wh, "#"L]; Put.Number[wh, network.pupHostNumber, [8, FALSE, TRUE, 0]]; Put.Text[wh, "#, NS net "L]; PutNetNumbers[wh, network.netNumber]; IF stats = NIL THEN RETURN; Put.Text[wh, ", Line "L]; Put.LongDecimal[wh, stats.lineNumber]; Put.Text[wh, ", "L]; Put.LongDecimal[wh, stats.speed]; Put.Text[wh, "KB"L]; SELECT TRUE FROM stats.remoteHostNumber = System.nullHostNumber => Put.Text[wh, " Down"L]; stats.remoteHostNumber = System.localHostNumber => Put.Text[wh, " Looped"L]; ENDCASE => BEGIN Put.CR[wh]; Put.Text[wh, "Up to "L]; PutHostNumbers[wh, stats.remoteHostNumber]; END; Put.CR[wh]; Put.Text[wh, "Recv: pkts "L]; Put.LongDecimal[wh, stats.stats[pktsReceived]]; Put.Text[wh, ", bytes "L]; Put.LongDecimal[wh, stats.stats[bytesReceived]]; Put.Text[wh, ", rejected "L]; Put.LongDecimal[wh, stats.stats[pktsRejected]]; Put.Text[wh, ", missed "L]; Put.LongDecimal[wh, stats.stats[rcvErrorNoGet]]; Put.Text[wh, ", idle "L]; Put.LongDecimal[wh, stats.stats[tooLongSinceLastReceive]]; Put.CR[wh]; Put.Text[wh, " Bad crc "L]; Put.LongDecimal[wh, stats.stats[rcvErrorCRC]]; Put.Text[wh, ", data lost "L]; Put.LongDecimal[wh, stats.stats[rcvErrorDataLost]]; Put.Text[wh, ", device error "L]; Put.LongDecimal[wh, stats.stats[rcvDeviceError]]; Put.Text[wh, ", timeout "L]; Put.LongDecimal[wh, stats.stats[rcvErrorFrameTimeout]]; Put.Text[wh, ", other error "L]; Put.LongDecimal[wh, stats.stats[rcvErrorUnknown]]; Put.CR[wh]; Put.Text[wh, "Send: pkts "L]; Put.LongDecimal[wh, stats.stats[pktsSent]]; Put.Text[wh, ", bytes "L]; Put.LongDecimal[wh, stats.stats[bytesSent]]; Put.CR[wh]; Put.Text[wh, " NS "L]; Put.LongDecimal[wh, stats.stats[nsSent]]; Put.Text[wh, " "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.nsBytesSend]]; Put.Text[wh, ", Pups "L]; Put.LongDecimal[wh, stats.stats[pupSent]]; Put.Text[wh, " "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.pupBytesSend]]; Put.Text[wh, ", Leaf "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.leafPktsSend]]; Put.Text[wh, " "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.leafBytesSend]]; Put.CR[wh]; IF stats.stats[sendErrorBadStatus] # 0 OR stats.stats[queueTooOld] # 0 THEN { Put.Text[wh, " Bad "L]; Put.LongDecimal[wh, stats.stats[sendErrorBadStatus]]; Put.Text[wh, ", stuck "L]; Put.LongDecimal[wh, stats.stats[queueTooOld]]; Put.CR[wh]; }; Put.Text[wh, " Queue too long "L]; Put.LongDecimal[wh, stats.stats[congestion]]; Put.Text[wh, ", NS "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.nsCongestion]]; Put.Text[wh, " Pup "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.pupCongestion]]; Put.CR[wh]; Put.Text[wh, " Conn too greedy "L]; Put.LongDecimal[wh, stats.stats[connTooGreedy]]; Put.Text[wh, ", NS "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.nsTooGreedy]]; Put.Text[wh, ", Pup "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.pupTooGreedy]]; Put.CR[wh]; IF stats.stats[PhoneNetExtras.nsDupsFiltered] # 0 THEN { Put.Text[wh, " NS duplicates discarded: "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.nsDupsFiltered]]; Put.CR[wh]; }; IF stats.stats[PhoneNetExtras.pupDupsFiltered] # 0 THEN { Put.Text[wh, " BSP probes/duplicates discarded: "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.pupDupsFiltered]]; Put.CR[wh]; }; IF stats.stats[PhoneNetExtras.leafDupsFiltered] # 0 THEN { Put.Text[wh, " Leaf duplicates discarded: "L]; Put.LongDecimal[wh, stats.stats[PhoneNetExtras.leafDupsFiltered]]; Put.CR[wh]; }; END; PutHostNumbers: PROCEDURE [wh: Window.Handle, net: System.HostNumber] = BEGIN Put.HostNumber[wh, net, productSoftware]; Put.Text[wh, "="L]; Put.HostNumber[wh, net, octal]; END; PutNetNumbers: PROCEDURE [wh: Window.Handle, net: System.NetworkNumber] = BEGIN Put.NetworkNumber[wh, net, productSoftware]; Put.Text[wh, "="L]; Put.NetworkNumber[wh, net, octal]; END; PrintHeader: PROCEDURE [wh: Window.Handle, s: LONG STRING, cr: BOOLEAN ← TRUE] = BEGIN Put.CR[wh]; Put.Date[wh, Time.Current[], dateTime]; Put.Text[wh, " "L]; Put.Text[wh, s]; IF cr THEN Put.CR[wh]; END; DoSomeYields: PROCEDURE = BEGIN THROUGH [0..100) DO Process.Yield[]; ENDLOOP; END; SetupDeviceMenu: PUBLIC PROCEDURE = BEGIN Items: TYPE = RECORD[SEQUENCE COMPUTED CARDINAL OF Menu.ItemObject]; items: LONG POINTER TO Items; firstNetwork: Driver.Network ← Driver.GetDeviceChain[]; devices: CARDINAL ← 0; FOR network: Driver.Network ← firstNetwork, network.next UNTIL network = NIL DO devices ← devices + 1; ENDLOOP; items ← z.NEW[Items[devices]]; devices ← 0; FOR network: Driver.Network ← firstNetwork, network.next UNTIL network = NIL DO tag: STRING = [30]; new: LONG STRING; SELECT network.device FROM ethernetOne => String.AppendString[tag, "Ether1"L]; ethernet => String.AppendString[tag, "Ether"L]; sla => String.AppendString[tag, "SLA"L]; phonenet => String.AppendString[tag, "PhoneNet"L]; ENDCASE => ERROR; String.AppendChar[tag, '-]; String.AppendNumber[tag, network.pupNetNumber, 8]; new ← z.NEW[StringBody[tag.length]]; String.AppendString[new, tag]; items[devices] ← [new, DoMenu]; devices ← devices + 1; ENDLOOP; Menu.Instantiate[ Menu.Create[DESCRIPTOR[items, devices], "DeviceInfo"], UserInput.GetDefaultWindow[]]; END; -- Initialization SetupDeviceMenu[]; END.