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