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