-- Copyright (C) 1981, 1983, 1985 by Xerox Corporation. All rights reserved. -- EnquiryPup.mesa, HGM, 30-Aug-85 17:24:31 -- From OthelloPup.mesa of 12-Jul-83 16:44:29. DIRECTORY Ascii USING [CR], Buffer USING [GetBuffer, ReturnBuffer], Driver USING [Network, GetDeviceChain], EnquiryDefs USING [Handle], EthernetDriverFriends USING [EtherStatsInfo], Format USING [NetworkNumber], GlassDefs USING [TimeOut], Process USING [Detach, Yield], Protocol1 USING [GetContext], PupDefs USING [ AppendPupAddress, DataWordsPerPupBuffer, GetPupAddress, GetPupContentsBytes, PupBuffer, PupNameTrouble, PupSocket, PupSocketDestroy, PupSocketMake, SecondsToTocks, SetPupContentsBytes], PupRouterDefs USING [GetRoutingTable, NetworkContext, RoutingTableEntry, RoutingTableObject], PupPktOps USING [pupBuffers], PupTypes USING [echoSoc, fillInSocketID, maxDataWordsPerGatewayPup, PupAddress], RoutingTable USING [NetworkContext], String USING [AppendNumber], System USING [NetworkNumber]; EnquiryPup: PROGRAM IMPORTS Buffer, Driver, Format, GlassDefs, Process, Protocol1, PupDefs, PupPktOps, PupRouterDefs, String EXPORTS Buffer, EnquiryDefs = BEGIN Network: PUBLIC TYPE = Driver.Network; PupEcho: PUBLIC PROC [str: EnquiryDefs.Handle, target: LONG STRING] = BEGIN OPEN PupDefs, PupTypes; bytesPerBuffer: CARDINAL; funny, late: LONG CARDINAL ← 0; recv, sent: LONG CARDINAL ← 0; wrong: LONG CARDINAL ← 0; me, where: PupAddress ← [, , echoSoc]; mySoc: PupSocket; packetNumber: CARDINAL ← 0; pleaseStop: BOOLEAN ← FALSE; routing: PupRouterDefs.RoutingTableEntry; context: PupRouterDefs.NetworkContext; Watch: PROC = {[] ← str.ReadChar[ ! GlassDefs.TimeOut => CONTINUE ]; pleaseStop ← TRUE}; PrintErrorPup: PROC [b: PupDefs.PupBuffer] = { source: PupTypes.PupAddress ← b.pup.source; str.WriteChar[Ascii.CR]; IF b.pup.pupType = error THEN { len: CARDINAL = PupDefs.GetPupContentsBytes[b]; str.WriteString["[Error Pup, code="L]; WriteOctal[str, LOOPHOLE[b.pup.errorCode]]; str.WriteString[", from: "L]; PrintPupAddress[str, source]; str.WriteString["] "L]; FOR i: CARDINAL IN [0..len - 2*(10 + 1 + 1)) DO str.WriteChar[b.pup.errorText[i]] ENDLOOP} ELSE { str.WriteString[" ***** "L]; str.WriteString["Funny PupType = "L]; WriteOctal[str, LOOPHOLE[b.pup.pupType]]; str.WriteString[" ***** "L]; }; str.WriteChar[Ascii.CR]; }; str.WriteChar[Ascii.CR]; PupDefs.GetPupAddress[ @where, target ! PupNameTrouble => { FOR i: CARDINAL IN [0..e.length) DO str.WriteChar[e[i]]; ENDLOOP; str.WriteChar[Ascii.CR]; GOTO Return;}]; mySoc ← PupSocketMake[fillInSocketID, where, SecondsToTocks[2]]; me ← mySoc.getLocalAddress[]; str.WriteString[". ["L]; PrintPupAddress[str, me]; str.WriteString["] => ["L]; routing ← @PupRouterDefs.GetRoutingTable[][where.net]; IF routing = NIL OR routing.context = NIL THEN { str.WriteString["Can't reach that network"L]; GOTO Return;}; context ← routing.context; IF routing.hop # 0 THEN { WriteOctal[str, context.pupNetNumber]; str.WriteChar['#]; WriteOctal[str, routing.route]; str.WriteChar['#]; str.WriteString["] => ["L]; }; PrintPupAddress[str, where]; str.WriteChar[']]; str.WriteChar[Ascii.CR]; Process.Detach[FORK Watch[]]; bytesPerBuffer ← 2*MIN[DataWordsPerPupBuffer[], maxDataWordsPerGatewayPup]; UNTIL pleaseStop DO FOR len: CARDINAL IN [0..bytesPerBuffer] UNTIL pleaseStop DO b: PupBuffer ← Buffer.GetBuffer[ type: pup, function: send, aH: PupPktOps.pupBuffers]; b.pup.pupID.a ← b.pup.pupID.b ← (packetNumber ← packetNumber + 1); b.pup.pupType ← echoMe; SetPupContentsBytes[b, len]; FOR i: CARDINAL IN [0..len) DO b.pup.pupBytes[i] ← i ENDLOOP; mySoc.put[b]; sent ← sent + 1; Process.Yield[]; -- be sure we don't hog machine UNTIL (b ← mySoc.get[]) = NIL DO SELECT TRUE FROM (b.pup.pupType # iAmEcho) => {funny ← funny + 1; PrintErrorPup[b]; }; ((b.pup.pupID.a # packetNumber) OR (b.pup.pupID.b # packetNumber) OR (len # GetPupContentsBytes[b])) => { str.WriteChar['#]; late ← late + 1}; ENDCASE => { FOR i: CARDINAL IN [0..len) DO IF b.pup.pupBytes[i] # (i MOD 400B) THEN { wrong ← wrong + 1; str.WriteChar['~]; GOTO Wrong}; ENDLOOP; str.WriteChar['!]; recv ← recv + 1; EXIT}; Buffer.ReturnBuffer[b]; REPEAT Wrong => NULL; ENDLOOP; IF b # NIL THEN Buffer.ReturnBuffer[b] ELSE str.WriteChar['?]; str.SendNow[]; ENDLOOP; str.WriteChar[Ascii.CR]; ENDLOOP; PupSocketDestroy[mySoc]; str.WriteString["Out: "L]; str.WriteLongDecimal[sent]; str.WriteString[", In: "L]; str.WriteLongDecimal[recv]; IF sent # 0 THEN { -- Avoid divide by 0 str.WriteString[" ("L]; str.WriteLongDecimal[(recv*100)/sent]; str.WriteString["%)"L]; IF late # 0 THEN { str.WriteString["\nLate: "L]; str.WriteLongDecimal[late]; str.WriteString[" ("L]; str.WriteLongDecimal[(late*100)/sent]; str.WriteString["%)"L]; }; }; str.WriteString["\n"L]; IF funny # 0 THEN {str.WriteLongDecimal[funny]; str.WriteString[" funny.\n"L];}; IF wrong # 0 THEN {str.WriteLongDecimal[wrong]; str.WriteString[" wrong data.\n"L];}; EXITS Return => NULL; END; PupRoutingTable: PUBLIC PROC [str: EnquiryDefs.Handle] = BEGIN pupRt: LONG DESCRIPTOR FOR ARRAY OF PupRouterDefs.RoutingTableObject; k: CARDINAL ← 0; str.WriteChar[Ascii.CR]; str.WriteString["| Net Via Hops | Net Via Hops | Net Via Hops |\n"L]; str.WriteString["|-------------------|-------------------|-------------------|\n"L]; pupRt ← PupRouterDefs.GetRoutingTable[]; FOR i: CARDINAL IN [0..LENGTH[pupRt]) DO -- prints 4 chars, octal, no trailing B O4: PROC [n: CARDINAL] = BEGIN temp: STRING ← [50]; String.AppendNumber[temp, n, 8]; FOR i: CARDINAL IN [temp.length..4) DO str.WriteChar[' ]; ENDLOOP; str.WriteString[temp]; END; O3Z: PROC [n: CARDINAL] = { n ← n MOD 1000B; THROUGH [0..3) DO str.WriteChar['0 + (n/100B) MOD 10B]; n ← n*10B ENDLOOP}; rte: PupRouterDefs.RoutingTableEntry = @pupRt[i]; context: PupRouterDefs.NetworkContext = rte.context; IF context = NIL THEN LOOP; IF k = 0 THEN str.WriteChar['|]; O4[i]; O4[context.pupNetNumber]; str.WriteChar['#]; O3Z[IF rte.hop # 0 THEN rte.route ELSE context.pupHostNumber]; str.WriteChar['#]; O4[rte.hop]; str.WriteString[" |"L]; IF (k ← k + 1) = 3 THEN {str.WriteChar[Ascii.CR]; k ← 0}; ENDLOOP; IF k # 0 THEN str.WriteChar[Ascii.CR]; END; DriverStats: PUBLIC PROC [str: EnquiryDefs.Handle] = BEGIN firstNetwork: Driver.Network ← Driver.GetDeviceChain[]; str.WriteChar[Ascii.CR]; FOR network: Driver.Network ← firstNetwork, network.next UNTIL network = NIL DO SELECT network.device FROM ethernet, ethernetOne => BEGIN pup: PupRouterDefs.NetworkContext = Protocol1.GetContext[network, pup]; ns: RoutingTable.NetworkContext = Protocol1.GetContext[network, ns]; stats: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo ← network.stats; str.WriteString["Ethernet"L]; IF network.device = ethernetOne THEN str.WriteString["One"L]; str.WriteString[" Statistics for Pup "L]; WriteOctal[str, pup.pupNetNumber]; str.WriteString["#"L]; WriteOctal[str, pup.pupHostNumber]; str.WriteString["#, NS net "L]; WriteNetNumbers[str, ns.netNumber]; str.WriteChar[Ascii.CR]; IF stats = NIL THEN BEGIN str.WriteString["*** NO DRIVER STATS ***\n"L]; LOOP; END; str.WriteString[" Rcv: pkts "L]; str.WriteLongDecimal[stats.packetsRecv]; str.WriteString[", words "L]; str.WriteLongDecimal[stats.wordsRecv]; str.WriteString[", bad "L]; str.WriteLongDecimal[stats.badRecvStatus]; str.WriteString[", missed "L]; str.WriteLongDecimal[stats.packetsMissed]; IF stats.idleInput # 0 THEN BEGIN str.WriteString[", idle "L]; str.WriteLongDecimal[stats.idleInput]; END; str.WriteChar[Ascii.CR]; IF stats.badRecvStatus # 0 OR stats.okButDribble # 0 THEN BEGIN str.WriteString[" crc "L]; str.WriteLongDecimal[stats.badCrc]; str.WriteString[", bad alignment but ok crc "L]; str.WriteLongDecimal[stats.badAlignmentButOkCrc]; str.WriteString[", crc and bad alignment "L]; str.WriteLongDecimal[stats.crcAndBadAlignment]; str.WriteChar[Ascii.CR]; str.WriteString[" ok but dribble "L]; str.WriteLongDecimal[stats.okButDribble]; str.WriteString[", too long "L]; str.WriteLongDecimal[stats.packetTooLong]; str.WriteString[", overrun "L]; str.WriteLongDecimal[stats.overrun]; str.WriteChar[Ascii.CR]; END; str.WriteString[" Xmit: pkts "L]; str.WriteLongDecimal[stats.packetsSent]; str.WriteString[", words "L]; str.WriteLongDecimal[stats.wordsSent]; str.WriteString[", bad "L]; str.WriteLongDecimal[stats.badSendStatus]; str.WriteChar[Ascii.CR]; IF stats.stuckOutput # 0 OR stats.badSendStatus # 0 OR stats.tooManyCollisions # 0 THEN BEGIN str.WriteString[" underrun "L]; str.WriteLongDecimal[stats.underrun]; str.WriteString[", stuck "L]; str.WriteLongDecimal[stats.stuckOutput]; str.WriteString[", too many collisions "L]; str.WriteLongDecimal[stats.tooManyCollisions]; str.WriteChar[Ascii.CR]; END; str.WriteString[" Lds:"L]; FOR i: CARDINAL IN [0..16) DO str.WriteChar[' ]; str.WriteLongDecimal[stats.loadTable[i]]; ENDLOOP; str.WriteChar[Ascii.CR]; END; ENDCASE => NULL; ENDLOOP; END; WriteNetNumbers: PROCEDURE [str: EnquiryDefs.Handle, net: System.NetworkNumber] = BEGIN Push: PROCEDURE [s: LONG STRING, clientData: LONG POINTER] = BEGIN FOR i: CARDINAL IN [0..s.length) DO str.WriteChar[s[i]]; ENDLOOP; END; Format.NetworkNumber[Push, net, productSoftware]; str.WriteString["="L]; Format.NetworkNumber[Push, net, octal]; END; WriteOctal: PROC [str: EnquiryDefs.Handle, n: CARDINAL] = BEGIN temp: STRING ← [50]; String.AppendNumber[temp, n, 8]; str.WriteString[temp]; END; PrintPupAddress: PROC [str: EnquiryDefs.Handle, a: PupTypes.PupAddress] = BEGIN temp: STRING ← [50]; PupDefs.AppendPupAddress[temp, a]; str.WriteString[temp]; END; END.....