-- File: ForwarderStats.mesa,  Last Edit: HGM  March 17, 1981  6:35 PM

DIRECTORY
  StatsDefs USING [StatCounterIndex, StatsGetCounters],
  InlineDefs USING [MesaToBcplLongNumber],
  ForwarderDefs USING [
    GetPointerToPupGateStats, ForwardStatsEntry, TransitMatrixEntry,
    statGateInfoReplies, forwardVersion, forwarderStatsReply],
  PupDefs USING [PupBuffer, ReturnPup],
  DriverDefs USING [GetDeviceChain, Network];

ForwarderStats: PROGRAM
  IMPORTS InlineDefs, StatsDefs, ForwarderDefs, PupDefs, DriverDefs
  EXPORTS ForwarderDefs =
  BEGIN OPEN PupDefs;

  stats: POINTER TO ARRAY StatsDefs.StatCounterIndex OF LONG CARDINAL =
    StatsDefs.StatsGetCounters[];

  -- This may be too soon (before initialization), and/or too late (page fault)
  firstNetwork: DriverDefs.Network ← DriverDefs.GetDeviceChain[];

  ForwarderStats: PUBLIC PROCEDURE [b: PupBuffer] =
    BEGIN OPEN ForwarderDefs;
    packets: POINTER TO ARRAY [0..0) OF LONG CARDINAL;
    bytes: POINTER TO ARRAY [0..0) OF LONG CARDINAL;
    nets: CARDINAL;
    AddStat: PROCEDURE [s, d: CARDINAL, n: LONG CARDINAL] =
      BEGIN
      IF n = 0 THEN RETURN;
      -- should test for buffer overflow
      t ← t + 1;
      tme↑ ← [s, d, InlineDefs.MesaToBcplLongNumber[n]];
      tme ← tme + SIZE[TransitMatrixEntry];
      END;
    n, t, length: CARDINAL ← 0;
    from, to: DriverDefs.Network;
    fse: LONG POINTER TO ForwardStatsEntry;
    tme: LONG POINTER TO TransitMatrixEntry;
    [packets, bytes, nets] ← ForwarderDefs.GetPointerToPupGateStats[];
    fse ← LOOPHOLE[@b.pupWords];
    length ← SIZE[ForwardStatsEntry];
    FOR from ← firstNetwork, from.next UNTIL from = NIL DO
      b.pupWords[length + n] ← from.netNumber.b MOD 400B; n ← n + 1; ENDLOOP;
    length ← length + n;
    tme ← LOOPHOLE[@b.pupWords + length];
    IF packets#NIL THEN
      BEGIN
      FOR from ← firstNetwork, from.next UNTIL from = NIL DO
        AddStat[from.netNumber.b, 0, packets[from.index + 0*nets]];
        FOR to ← firstNetwork, to.next UNTIL to = NIL DO
          AddStat[
            from.netNumber.b, to.netNumber.b, packets[from.index + to.index*nets]];
          ENDLOOP;
        ENDLOOP;
      END;
    IF bytes#NIL THEN
      BEGIN
      FOR from ← firstNetwork, from.next UNTIL from = NIL DO
        AddStat[from.netNumber.b, 0, bytes[from.index + 0*nets]];
        FOR to ← firstNetwork, to.next UNTIL to = NIL DO
          AddStat[
            from.netNumber.b, to.netNumber.b, bytes[from.index + to.index*nets]];
          ENDLOOP;
        ENDLOOP;
      END;
    length ← length + t*SIZE[ForwardStatsEntry];
    fse↑ ←
      [version: forwardVersion,
	routingInfoRequests: InlineDefs.MesaToBcplLongNumber[
	stats[statGateInfoReplies]], numberOfNetworks: n, numberOfTMEs: t];
    ReturnPup[b, forwarderStatsReply, 2*length];
    END;

  END.