LCOV - code coverage report
Current view: top level - app/firedancer/commands/monitor_gossip - gossip_diag.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 511 0.0 %
Date: 2026-03-19 18:19:27 Functions: 0 9 0.0 %

          Line data    Source code
       1             : #include "gossip_diag.h"
       2             : 
       3             : #include <stdio.h>
       4             : #include <stdlib.h>
       5             : #include <string.h>
       6             : 
       7             : /* Formatting helpers *************************************************/
       8             : 
       9             : static char *
      10           0 : fmt_count( char buf[ static 64 ], ulong count ) {
      11           0 :   char tmp[ 64 ];
      12           0 :   if( FD_LIKELY( count<1000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%lu", count ) );
      13           0 :   else if( FD_LIKELY( count<1000000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f K", (double)count/1000.0 ) );
      14           0 :   else if( FD_LIKELY( count<1000000000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f M", (double)count/1000000.0 ) );
      15           0 :   else FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f G", (double)count/1000000000.0 ) );
      16             : 
      17           0 :   FD_TEST( fd_cstr_printf_check( buf, 64UL, NULL, "%12s", tmp ) );
      18           0 :   return buf;
      19           0 : }
      20             : 
      21             : static char *
      22           0 : fmt_bytes( char buf[ static 64 ], ulong bytes ) {
      23           0 :   char tmp[ 64 ];
      24           0 :   if( FD_LIKELY( 8UL*bytes<1000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%lu bits", 8UL*bytes ) );
      25           0 :   else if( FD_LIKELY( 8UL*bytes<1000000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f Kbit", (double)(8UL*bytes)/1000.0 ) );
      26           0 :   else if( FD_LIKELY( 8UL*bytes<1000000000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f Mbit", (double)(8UL*bytes)/1000000.0 ) );
      27           0 :   else FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f Gbit", (double)(8UL*bytes)/1000000000.0 ) );
      28             : 
      29           0 :   FD_TEST( fd_cstr_printf_check( buf, 64UL, NULL, "%12s", tmp ) );
      30           0 :   return buf;
      31           0 : }
      32             : 
      33             : static char *
      34           0 : fmt_pct( char buf[ static 64 ], double pct ) {
      35           0 :   char tmp[ 64 ];
      36           0 :   FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f %%", 100.0*pct ) );
      37           0 :   FD_TEST( fd_cstr_printf_check( buf, 64UL, NULL, "%12s", tmp ) );
      38           0 :   return buf;
      39           0 : }
      40             : 
      41             : /* Gossvf tile collection *********************************************/
      42             : 
      43             : static fd_gossip_diag_gossvf_t
      44           0 : collect_gossvf_tiles( fd_topo_t * topo ) {
      45           0 :   fd_gossip_diag_gossvf_t tiles = {0};
      46           0 :   tiles.tile_count = fd_topo_tile_name_cnt( topo, "gossvf" );
      47             : 
      48           0 :   if( FD_UNLIKELY( tiles.tile_count == 0UL ) ) {
      49           0 :     return tiles;
      50           0 :   }
      51             : 
      52           0 :   tiles.tiles = aligned_alloc( 8UL, tiles.tile_count * sizeof(fd_topo_tile_t*) );
      53           0 :   FD_TEST( tiles.tiles );
      54           0 :   tiles.metrics = aligned_alloc( 8UL, tiles.tile_count * sizeof(volatile ulong*) );
      55           0 :   FD_TEST( tiles.metrics );
      56           0 :   tiles.prev_metrics = aligned_alloc( 8UL, tiles.tile_count * sizeof(ulong*) );
      57           0 :   FD_TEST( tiles.prev_metrics );
      58           0 :   tiles.net_links = aligned_alloc( 8UL, tiles.tile_count * sizeof(volatile ulong*) );
      59           0 :   FD_TEST( tiles.net_links );
      60             : 
      61           0 :   for( ulong i = 0UL; i < tiles.tile_count; i++ ) {
      62           0 :     ulong tile_idx = fd_topo_find_tile( topo, "gossvf", i );
      63           0 :     FD_TEST( tile_idx != ULONG_MAX );
      64             : 
      65           0 :     tiles.tiles[i] = &topo->tiles[ tile_idx ];
      66           0 :     tiles.metrics[i] = fd_metrics_tile( tiles.tiles[i]->metrics );
      67           0 :     FD_TEST( tiles.metrics[i] );
      68             : 
      69           0 :     tiles.prev_metrics[i] = aligned_alloc( 8UL, FD_METRICS_TOTAL_SZ );
      70           0 :     FD_TEST( tiles.prev_metrics[i] );
      71           0 :     memset( tiles.prev_metrics[i], 0, FD_METRICS_TOTAL_SZ );
      72             : 
      73           0 :     tiles.net_links[i] = fd_metrics_link_in( tiles.tiles[i]->metrics, 0UL );
      74           0 :     FD_TEST( tiles.net_links[i] );
      75           0 :   }
      76             : 
      77           0 :   return tiles;
      78           0 : }
      79             : 
      80             : /* Aggregation helpers ************************************************/
      81             : 
      82             : static ulong
      83           0 : aggregate_gossvf_counter( fd_gossip_diag_gossvf_t * tiles, ulong metric_idx ) {
      84           0 :   ulong total = 0UL;
      85           0 :   for( ulong i = 0UL; i < tiles->tile_count; i++ ) {
      86           0 :     total += tiles->metrics[i][metric_idx];
      87           0 :   }
      88           0 :   return total;
      89           0 : }
      90             : 
      91             : static ulong
      92           0 : aggregate_gossvf_prev_counter( fd_gossip_diag_gossvf_t * tiles, ulong metric_idx ) {
      93           0 :   ulong total = 0UL;
      94           0 :   for( ulong i = 0UL; i < tiles->tile_count; i++ ) {
      95           0 :     total += tiles->prev_metrics[i][metric_idx];
      96           0 :   }
      97           0 :   return total;
      98           0 : }
      99             : 
     100             : /* rx_deltas computation **********************************************/
     101             : 
     102             : static rx_deltas_t
     103             : rx_deltas_aggregated( volatile ulong * gossip_metrics,
     104             :                       ulong *          gossip_prev,
     105           0 :                       fd_gossip_diag_gossvf_t * gossvf_tiles ) {
     106           0 :   rx_deltas_t deltas;
     107             : 
     108             :   /* Pull request metrics aggregated across all gossvf tiles */
     109           0 :   ulong pull_request_rx_current =
     110           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_REQUEST ) ) +
     111           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     112           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     113           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     114           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     115           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     116           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ) +
     117           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_MASK_BITS ) );
     118             : 
     119           0 :   ulong pull_request_rx_prev =
     120           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_REQUEST ) ) +
     121           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     122           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     123           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     124           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     125           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     126           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ) +
     127           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_MASK_BITS ) );
     128             : 
     129           0 :   deltas.pull_request_rx = pull_request_rx_current - pull_request_rx_prev;
     130             : 
     131           0 :   deltas.pull_request_rx_drop =
     132           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     133           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     134           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     135           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     136           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     137           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ) +
     138           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_MASK_BITS ) )) -
     139           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     140           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     141           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     142           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     143           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     144           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ) +
     145           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_MASK_BITS ) ));
     146             : 
     147           0 :   deltas.pull_request_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_REQUEST ) ] -
     148           0 :                            gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_REQUEST ) ];
     149           0 :   deltas.pull_request_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_REQUEST ) ] -
     150           0 :                                  gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_REQUEST ) ];
     151             : 
     152           0 :   deltas.pull_request_rx_bytes =
     153           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_REQUEST ) ) +
     154           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     155           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     156           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     157           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     158           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     159           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SHRED_VERSION ) ) +
     160           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_MASK_BITS ) )) -
     161           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_REQUEST ) ) +
     162           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     163           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     164           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     165           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     166           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     167           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SHRED_VERSION ) ) +
     168           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_MASK_BITS ) ));
     169             : 
     170             :   /* Pull response metrics */
     171           0 :   deltas.pull_response_rx =
     172           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) ) +
     173           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) )) -
     174           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) ) +
     175           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ));
     176             : 
     177           0 :   deltas.pull_response_rx_drop =
     178           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ) -
     179           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) );
     180             : 
     181           0 :   deltas.pull_response_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_RESPONSE ) ] -
     182           0 :                             gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_RESPONSE ) ];
     183           0 :   deltas.pull_response_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_RESPONSE ) ] -
     184           0 :                                   gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_RESPONSE ) ];
     185           0 :   deltas.pull_response_rx_bytes =
     186           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_RESPONSE ) ) +
     187           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) )) -
     188           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_RESPONSE ) ) +
     189           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ));
     190             : 
     191             :   /* Push metrics */
     192           0 :   deltas.push_rx =
     193           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) ) +
     194           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) )) -
     195           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) ) +
     196           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) ));
     197             : 
     198           0 :   deltas.push_rx_drop =
     199           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) ) -
     200           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) );
     201             : 
     202           0 :   deltas.push_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PUSH ) ] -
     203           0 :                    gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PUSH ) ];
     204           0 :   deltas.push_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PUSH ) ] -
     205           0 :                          gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PUSH ) ];
     206           0 :   deltas.push_rx_bytes =
     207           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PUSH ) ) +
     208           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PUSH_NO_VALID_CRDS ) )) -
     209           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PUSH ) ) +
     210           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PUSH_NO_VALID_CRDS ) ));
     211             : 
     212             :   /* Prune metrics */
     213           0 :   deltas.prune_rx =
     214           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PRUNE ) ) +
     215           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ) +
     216           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ) +
     217           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) )) -
     218           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PRUNE ) ) +
     219           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ) +
     220           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ) +
     221           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) ));
     222             : 
     223           0 :   deltas.prune_rx_drop =
     224           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ) +
     225           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ) +
     226           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) )) -
     227           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ) +
     228           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ) +
     229           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) ));
     230             : 
     231           0 :   deltas.prune_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PRUNE ) ] -
     232           0 :                     gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PRUNE ) ];
     233           0 :   deltas.prune_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PRUNE ) ] -
     234           0 :                           gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PRUNE ) ];
     235           0 :   deltas.prune_rx_bytes =
     236           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PRUNE ) ) +
     237           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_DESTINATION ) ) +
     238           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_WALLCLOCK ) ) +
     239           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_SIGNATURE ) )) -
     240           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PRUNE ) ) +
     241           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_DESTINATION ) ) +
     242           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_WALLCLOCK ) ) +
     243           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_SIGNATURE ) ));
     244             : 
     245             :   /* Ping metrics */
     246           0 :   deltas.ping_rx =
     247           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PING ) ) +
     248           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) )) -
     249           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PING ) ) +
     250           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) ));
     251             : 
     252           0 :   deltas.ping_rx_drop =
     253           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) ) -
     254           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) );
     255             : 
     256           0 :   deltas.ping_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PING ) ] -
     257           0 :                    gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PING ) ];
     258           0 :   deltas.ping_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PING ) ] -
     259           0 :                          gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PING ) ];
     260           0 :   deltas.ping_rx_bytes =
     261           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PING ) ) +
     262           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PING_SIGNATURE ) )) -
     263           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PING ) ) +
     264           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PING_SIGNATURE ) ));
     265             : 
     266             :   /* Pong metrics */
     267           0 :   deltas.pong_rx =
     268           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PONG ) ) +
     269           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) )) -
     270           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PONG ) ) +
     271           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) ));
     272             : 
     273           0 :   deltas.pong_rx_drop =
     274           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) ) -
     275           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) );
     276             : 
     277           0 :   deltas.pong_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PONG ) ] -
     278           0 :                    gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PONG ) ];
     279           0 :   deltas.pong_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PONG ) ] -
     280           0 :                          gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PONG ) ];
     281           0 :   deltas.pong_rx_bytes =
     282           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PONG ) ) +
     283           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PONG_SIGNATURE ) )) -
     284           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PONG ) ) +
     285           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PONG_SIGNATURE ) ));
     286             : 
     287           0 :   return deltas;
     288           0 : }
     289             : 
     290             : /* Public API *********************************************************/
     291             : 
     292             : int
     293             : fd_gossip_diag_init( fd_gossip_diag_ctx_t * ctx,
     294             :                      fd_topo_t *            topo,
     295           0 :                      config_t *             config ) {
     296           0 :   memset( ctx, 0, sizeof(*ctx) );
     297           0 :   ctx->topo   = topo;
     298           0 :   ctx->config = config;
     299           0 :   ctx->is_xdp = ( 0==strcmp( config->net.provider, "xdp" ) );
     300             : 
     301             :   /* Find gossip tile */
     302           0 :   ulong gossip_tile_idx = fd_topo_find_tile( topo, "gossip", 0UL );
     303           0 :   if( FD_UNLIKELY( gossip_tile_idx==ULONG_MAX ) ) {
     304           0 :     FD_LOG_WARNING(( "No gossip tile found in topology" ));
     305           0 :     return -1;
     306           0 :   }
     307           0 :   ctx->gossip_tile    = &topo->tiles[ gossip_tile_idx ];
     308           0 :   ctx->gossip_metrics = fd_metrics_tile( ctx->gossip_tile->metrics );
     309           0 :   if( FD_UNLIKELY( !ctx->gossip_metrics ) ) {
     310           0 :     FD_LOG_WARNING(( "Failed to get gossip tile metrics" ));
     311           0 :     return -1;
     312           0 :   }
     313             : 
     314           0 :   ctx->gossip_prev = aligned_alloc( 8UL, FD_METRICS_TOTAL_SZ );
     315           0 :   FD_TEST( ctx->gossip_prev );
     316           0 :   memset( ctx->gossip_prev, 0, FD_METRICS_TOTAL_SZ );
     317             : 
     318             :   /* Collect gossvf tiles */
     319           0 :   ctx->gossvf = collect_gossvf_tiles( topo );
     320           0 :   if( FD_UNLIKELY( ctx->gossvf.tile_count==0UL ) ) {
     321           0 :     FD_LOG_WARNING(( "No gossvf tiles found in topology" ));
     322           0 :     return -1;
     323           0 :   }
     324             : 
     325             :   /* Find net tiles */
     326           0 :   ctx->net_tile_cnt = config->layout.net_tile_count;
     327           0 :   ctx->net_metrics  = aligned_alloc( 8UL, ctx->net_tile_cnt * sizeof(volatile ulong const *) );
     328           0 :   FD_TEST( ctx->net_metrics );
     329           0 :   for( ulong i=0UL; i<ctx->net_tile_cnt; i++ ) {
     330           0 :     ulong net_tile_idx = fd_topo_find_tile( topo, ctx->is_xdp ? "net" : "sock", i );
     331           0 :     if( FD_UNLIKELY( net_tile_idx==ULONG_MAX ) ) {
     332           0 :       FD_LOG_WARNING(( "Net tile %lu not found", i ));
     333           0 :       return -1;
     334           0 :     }
     335           0 :     fd_topo_tile_t * net_tile = &topo->tiles[ net_tile_idx ];
     336           0 :     ctx->net_metrics[ i ] = fd_metrics_tile( net_tile->metrics );
     337           0 :     FD_TEST( ctx->net_metrics[ i ] );
     338           0 :   }
     339             : 
     340           0 :   ctx->prev_net_tx_bytes = aligned_alloc( 8UL, ctx->net_tile_cnt * sizeof(ulong) );
     341           0 :   ctx->prev_net_rx_bytes = aligned_alloc( 8UL, ctx->net_tile_cnt * sizeof(ulong) );
     342           0 :   FD_TEST( ctx->prev_net_tx_bytes );
     343           0 :   FD_TEST( ctx->prev_net_rx_bytes );
     344           0 :   memset( ctx->prev_net_tx_bytes, 0, ctx->net_tile_cnt * sizeof(ulong) );
     345           0 :   memset( ctx->prev_net_rx_bytes, 0, ctx->net_tile_cnt * sizeof(ulong) );
     346             : 
     347           0 :   ctx->net0_link         = ctx->gossvf.net_links[0];
     348           0 :   ctx->prev_net0_rx_bytes = 0UL;
     349             : 
     350           0 :   return 0;
     351           0 : }
     352             : 
     353             : void
     354             : fd_gossip_diag_render( fd_gossip_diag_ctx_t * ctx,
     355           0 :                        int                    compact_mode ) {
     356           0 :   volatile ulong * gossip_metrics = ctx->gossip_metrics;
     357           0 :   ulong *          gossip_prev    = ctx->gossip_prev;
     358             : 
     359           0 :   ulong total_crds = 0UL;
     360           0 :   for( ulong i=0UL; i<FD_METRICS_ENUM_CRDS_VALUE_CNT; i++ ) total_crds += gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT )+i ];
     361           0 :   ulong total_contact_infos = gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_CONTACT_INFO_V2 ) ];
     362             : 
     363           0 :   ctx->last_total_crds          = total_crds;
     364           0 :   ctx->last_total_contact_infos = total_contact_infos;
     365             : 
     366           0 :   if( compact_mode ) {
     367           0 :     printf( "Table Size: %lu,\tContact Infos: %lu\n",
     368           0 :             total_crds,
     369           0 :             total_contact_infos );
     370           0 :     return;
     371           0 :   }
     372             : 
     373           0 :   char buf1[ 64 ], buf2[ 64 ], buf3[ 64 ], buf4[ 64 ], buf5[ 64 ];
     374             : 
     375           0 :   ulong total_overrun = 0UL;
     376           0 :   for( ulong i = 0UL; i < ctx->gossvf.tile_count; i++ ) {
     377           0 :     volatile ulong * net_vf_link = ctx->gossvf.net_links[i];
     378           0 :     ulong overrun_count = net_vf_link[ MIDX( COUNTER, LINK, OVERRUN_POLLING_FRAG_COUNT ) ] +
     379           0 :                           net_vf_link[ MIDX( COUNTER, LINK, OVERRUN_READING_FRAG_COUNT ) ];
     380           0 :     total_overrun += overrun_count;
     381           0 :   }
     382           0 :   printf( " Total Overrun: %s\n", fmt_count( buf1, total_overrun ) );
     383           0 :   printf( " Total ping tracked: %lu\n", gossip_metrics[ MIDX( COUNTER, GOSSIP, PING_TRACKED_COUNT ) ] );
     384             : 
     385           0 :   for( ulong i=0UL; i<ctx->net_tile_cnt; i++ ) {
     386           0 :     if( FD_LIKELY( ctx->is_xdp ) ) {
     387           0 :       printf( " Net %lu RX bw %s, TX bw %s .. %s %s\n", i,
     388           0 :               fmt_bytes( buf1, ctx->net_metrics[ i ][ MIDX( COUNTER, NET,  RX_BYTES_TOTAL ) ] - ctx->prev_net_rx_bytes[ i ] ),
     389           0 :               fmt_bytes( buf2, ctx->net_metrics[ i ][ MIDX( COUNTER, NET,  TX_BYTES_TOTAL ) ] - ctx->prev_net_tx_bytes[ i ] ),
     390           0 :               fmt_count( buf3, ctx->net_metrics[ i ][ MIDX( COUNTER, NET,  RX_FILL_BLOCKED_CNT ) ] ),
     391           0 :               fmt_count( buf4, ctx->net_metrics[ i ][ MIDX( COUNTER, NET,  RX_BACKPRESSURE_CNT ) ] ) );
     392           0 :       ctx->prev_net_rx_bytes[ i ] = ctx->net_metrics[ i ][ MIDX( COUNTER, NET,  RX_BYTES_TOTAL ) ];
     393           0 :       ctx->prev_net_tx_bytes[ i ] = ctx->net_metrics[ i ][ MIDX( COUNTER, NET,  TX_BYTES_TOTAL ) ];
     394           0 :     } else {
     395           0 :       printf( " Net %lu RX bw %s, TX bw %s\n", i,
     396           0 :               fmt_bytes( buf1, ctx->net_metrics[ i ][ MIDX( COUNTER, SOCK, RX_BYTES_TOTAL ) ] - ctx->prev_net_rx_bytes[ i ] ),
     397           0 :               fmt_bytes( buf2, ctx->net_metrics[ i ][ MIDX( COUNTER, SOCK, TX_BYTES_TOTAL ) ] - ctx->prev_net_tx_bytes[ i ] ) );
     398           0 :       ctx->prev_net_rx_bytes[ i ] = ctx->net_metrics[ i ][ MIDX( COUNTER, SOCK, RX_BYTES_TOTAL ) ];
     399           0 :       ctx->prev_net_tx_bytes[ i ] = ctx->net_metrics[ i ][ MIDX( COUNTER, SOCK, TX_BYTES_TOTAL ) ];
     400           0 :     }
     401           0 :   }
     402             : 
     403           0 :   printf( " Single Tile RX bw %s\n\n", fmt_bytes( buf1, ctx->net0_link[ MIDX( COUNTER, LINK, CONSUMED_SIZE_BYTES ) ] - ctx->prev_net0_rx_bytes ) );
     404           0 :   ctx->prev_net0_rx_bytes = ctx->net0_link[ MIDX( COUNTER, LINK, CONSUMED_SIZE_BYTES ) ];
     405             : 
     406           0 :   ulong message_unparseable = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_UNPARSEABLE ) );
     407           0 :   printf( " Message unparseable: %lu/??\n", message_unparseable );
     408             : 
     409           0 :   ulong pull_response_drops   = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) );
     410           0 :   ulong pull_response_success = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) );
     411           0 :   printf( " Pull response drops (no valid CRDS): %lu/%lu\n", pull_response_drops, pull_response_drops + pull_response_success );
     412             : 
     413           0 :   ulong crds_success           = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_SUCCESS_PULL_RESPONSE ) );
     414           0 :   ulong crds_duplicate         = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) );
     415           0 :   ulong crds_signature         = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_SIGNATURE ) );
     416           0 :   ulong crds_origin_no_contact = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_ORIGIN_NO_CONTACT_INFO ) );
     417           0 :   ulong crds_origin_shred      = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_ORIGIN_SHRED_VERSION ) );
     418           0 :   ulong crds_inactive          = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_INACTIVE ) );
     419           0 :   ulong crds_wallclock         = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_WALLCLOCK ) );
     420             : 
     421           0 :   ulong pull_response_crds_total = crds_success + crds_duplicate + crds_signature + crds_origin_no_contact + crds_origin_shred + crds_inactive + crds_wallclock;
     422             : 
     423           0 :   ulong prev_crds_success           = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_SUCCESS_PULL_RESPONSE ) );
     424           0 :   ulong prev_crds_duplicate         = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) );
     425           0 :   ulong prev_crds_signature         = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_SIGNATURE ) );
     426           0 :   ulong prev_crds_origin_no_contact = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_ORIGIN_NO_CONTACT_INFO ) );
     427           0 :   ulong prev_crds_origin_shred      = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_ORIGIN_SHRED_VERSION ) );
     428           0 :   ulong prev_crds_inactive          = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_INACTIVE ) );
     429           0 :   ulong prev_crds_wallclock         = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_WALLCLOCK ) );
     430             : 
     431           0 :   ulong prev_pull_response_crds_total = prev_crds_success + prev_crds_duplicate + prev_crds_signature + prev_crds_origin_no_contact + prev_crds_origin_shred + prev_crds_inactive + prev_crds_wallclock;
     432             : 
     433           0 :   printf( " Pull response CRDS drops: (%lu/%lu) %.1f %% (%.1f %% duplicate, %.1f %% signature, %.1f %% origin no contact info, %.1f %% origin shred version, %.1f %% inactive, %.1f %% wallclock)\n",
     434           0 :           pull_response_crds_total - crds_success,
     435           0 :           pull_response_crds_total,
     436           0 :           ((double)pull_response_crds_total - (double)crds_success ) / (double)pull_response_crds_total * 100.0,
     437           0 :           (double)crds_duplicate / (double)pull_response_crds_total * 100.0,
     438           0 :           (double)crds_signature / (double)pull_response_crds_total * 100.0,
     439           0 :           (double)crds_origin_no_contact / (double)pull_response_crds_total * 100.0,
     440           0 :           (double)crds_origin_shred / (double)pull_response_crds_total * 100.0,
     441           0 :           (double)crds_inactive / (double)pull_response_crds_total * 100.0,
     442           0 :           (double)crds_wallclock / (double)pull_response_crds_total * 100.0 );
     443             : 
     444           0 :   printf( " Pull response CRDS inc drops: (%lu/%lu) %1.f %% (%.1f %% duplicate, %.1f %% signature, %.1f %% origin no contact info, %.1f %% origin shred version, %.1f %% inactive, %.1f %% wallclock)\n\n",
     445           0 :           (pull_response_crds_total - prev_pull_response_crds_total) - (crds_success - prev_crds_success),
     446           0 :           pull_response_crds_total - prev_pull_response_crds_total,
     447           0 :           ((double)(pull_response_crds_total - prev_pull_response_crds_total) - (double)(crds_success - prev_crds_success) ) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     448           0 :           (double)(crds_duplicate - prev_crds_duplicate) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     449           0 :           (double)(crds_signature - prev_crds_signature) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     450           0 :           (double)(crds_origin_no_contact - prev_crds_origin_no_contact) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     451           0 :           (double)(crds_origin_shred - prev_crds_origin_shred) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     452           0 :           (double)(crds_inactive - prev_crds_inactive) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     453           0 :           (double)(crds_wallclock - prev_crds_wallclock) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0 );
     454             : 
     455           0 :   ulong pull_response_insertion_total = gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ] +
     456           0 :                                         gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_STALE ) ] +
     457           0 :                                         gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) ];
     458           0 :   ulong prev_pull_response_insertion_total = gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ] +
     459           0 :                                              gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_STALE ) ] +
     460           0 :                                              gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) ];
     461             : 
     462           0 :   printf( " Pull response CRDS insertion drops: (%lu/%lu) %.1f %% (%.1f %% no override, %.1f %% hash duplicate)\n",
     463           0 :           pull_response_insertion_total - gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ],
     464           0 :           pull_response_insertion_total,
     465           0 :           ((double)pull_response_insertion_total - (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ] ) / (double)pull_response_insertion_total * 100.0,
     466           0 :           (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_STALE ) ] / (double)pull_response_insertion_total * 100.0,
     467           0 :           (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) ] / (double)pull_response_insertion_total * 100.0 );
     468           0 :   printf( " Pull response CRDS insertion inc drops: (%lu/%lu) %.1f %% (%.1f %% no override, %.1f %% hash duplicate)\n\n",
     469           0 :           (pull_response_insertion_total - prev_pull_response_insertion_total) - (gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ]),
     470           0 :           pull_response_insertion_total - prev_pull_response_insertion_total,
     471           0 :           ((double)(pull_response_insertion_total - prev_pull_response_insertion_total) - (double)(gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ]) ) / (double)(pull_response_insertion_total - prev_pull_response_insertion_total) * 100.0,
     472           0 :           (double)(gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_STALE ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_STALE ) ]) / (double)(pull_response_insertion_total - prev_pull_response_insertion_total) * 100.0,
     473           0 :           (double)(gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) ]) / (double)(pull_response_insertion_total - prev_pull_response_insertion_total) * 100.0 );
     474             : 
     475             :   /* Push message statistics */
     476           0 :   ulong push_drops   = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) );
     477           0 :   ulong push_success = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) );
     478           0 :   printf( " Push drops: %lu/%lu\n", push_drops, push_drops + push_success );
     479             : 
     480           0 :   ulong push_crds_success           = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_SUCCESS_PUSH ) );
     481           0 :   ulong push_crds_signature         = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_SIGNATURE ) );
     482           0 :   ulong push_crds_origin_no_contact = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_ORIGIN_NO_CONTACT_INFO ) );
     483           0 :   ulong push_crds_origin_shred      = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_ORIGIN_SHRED_VERSION ) );
     484           0 :   ulong push_crds_inactive          = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_INACTIVE ) );
     485           0 :   ulong push_crds_wallclock         = aggregate_gossvf_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_WALLCLOCK ) );
     486             : 
     487           0 :   ulong push_crds_total = push_crds_success + push_crds_signature + push_crds_origin_no_contact + push_crds_origin_shred + push_crds_inactive + push_crds_wallclock;
     488             : 
     489           0 :   ulong prev_push_crds_success           = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_SUCCESS_PUSH ) );
     490           0 :   ulong prev_push_crds_signature         = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_SIGNATURE ) );
     491           0 :   ulong prev_push_crds_origin_no_contact = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_ORIGIN_NO_CONTACT_INFO ) );
     492           0 :   ulong prev_push_crds_origin_shred      = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_ORIGIN_SHRED_VERSION ) );
     493           0 :   ulong prev_push_crds_inactive          = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_INACTIVE ) );
     494           0 :   ulong prev_push_crds_wallclock         = aggregate_gossvf_prev_counter( &ctx->gossvf, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_WALLCLOCK ) );
     495             : 
     496           0 :   ulong prev_push_crds_total = prev_push_crds_success + prev_push_crds_signature + prev_push_crds_origin_no_contact + prev_push_crds_origin_shred + prev_push_crds_inactive + prev_push_crds_wallclock;
     497             : 
     498           0 :   printf( " Push CRDS drops: (%lu/%lu) %.1f %% (%.1f %% signature, %.1f %% origin no contact info, %.1f %% origin shred version, %.1f %% inactive, %.1f %% wallclock)\n",
     499           0 :           push_crds_total - push_crds_success,
     500           0 :           push_crds_total,
     501           0 :           ((double)push_crds_total - (double)push_crds_success ) / (double)push_crds_total * 100.0,
     502           0 :           (double)push_crds_signature / (double)push_crds_total * 100.0,
     503           0 :           (double)push_crds_origin_no_contact / (double)push_crds_total * 100.0,
     504           0 :           (double)push_crds_origin_shred / (double)push_crds_total * 100.0,
     505           0 :           (double)push_crds_inactive / (double)push_crds_total * 100.0,
     506           0 :           (double)push_crds_wallclock / (double)push_crds_total * 100.0 );
     507             : 
     508           0 :   printf( " Push CRDS inc drops: (%lu/%lu) %.1f %% (%.1f %% signature, %.1f %% origin no contact info, %.1f %% origin shred version, %.1f %% inactive, %.1f %% wallclock)\n\n",
     509           0 :           (push_crds_total - prev_push_crds_total) - (push_crds_success - prev_push_crds_success),
     510           0 :           push_crds_total - prev_push_crds_total,
     511           0 :           ((double)(push_crds_total - prev_push_crds_total) - (double)(push_crds_success - prev_push_crds_success) ) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
     512           0 :           (double)(push_crds_signature - prev_push_crds_signature) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
     513           0 :           (double)(push_crds_origin_no_contact - prev_push_crds_origin_no_contact) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
     514           0 :           (double)(push_crds_origin_shred - prev_push_crds_origin_shred) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
     515           0 :           (double)(push_crds_inactive - prev_push_crds_inactive) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
     516           0 :           (double)(push_crds_wallclock - prev_push_crds_wallclock) / (double)(push_crds_total - prev_push_crds_total) * 100.0 );
     517             : 
     518           0 :   ulong push_insertion_total = gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ] +
     519           0 :                                gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_STALE ) ] +
     520           0 :                                gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_DUPLICATE ) ];
     521           0 :   ulong prev_push_insertion_total = gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ] +
     522           0 :                                     gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_STALE ) ] +
     523           0 :                                     gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_DUPLICATE ) ];
     524             : 
     525           0 :   printf( " Push CRDS insertion drops: (%lu/%lu) %.1f %% (%.1f %% no override, %.1f %% hash duplicate)\n",
     526           0 :           push_insertion_total - gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ],
     527           0 :           push_insertion_total,
     528           0 :           ((double)push_insertion_total - (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ] ) / (double)push_insertion_total * 100.0,
     529           0 :           (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_STALE ) ] / (double)push_insertion_total * 100.0,
     530           0 :           (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_DUPLICATE ) ] / (double)push_insertion_total * 100.0 );
     531           0 :   printf( " Push CRDS insertion inc drops: (%lu/%lu) %.1f %% (%.1f %% no override, %.1f %% hash duplicate)\n\n",
     532           0 :           (push_insertion_total - prev_push_insertion_total) - (gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ]),
     533           0 :           push_insertion_total - prev_push_insertion_total,
     534           0 :           ((double)(push_insertion_total - prev_push_insertion_total) - (double)(gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ]) ) / (double)(push_insertion_total - prev_push_insertion_total) * 100.0,
     535           0 :           (double)(gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_STALE ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_STALE ) ]) / (double)(push_insertion_total - prev_push_insertion_total) * 100.0,
     536           0 :           (double)(gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_DUPLICATE ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_DUPLICATE ) ]) / (double)(push_insertion_total - prev_push_insertion_total) * 100.0 );
     537             : 
     538           0 :   printf( " +------------------------+--------------+  +------------+--------------+\n" );
     539           0 :   printf( " | CRDS Type              | Count        |  | Ping Type  | Count        |\n" );
     540           0 :   printf( " +------------------------+--------------+  +------------+--------------+\n" );
     541           0 :   printf( " | Contact Info V1        | %s |"        "  | Unpinged   | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_CONTACT_INFO_V1 ) ] ), fmt_count( buf2, gossip_metrics[ MIDX( GAUGE, GOSSIP, PING_TRACKER_COUNT_UNPINGED ) ] ) );
     542           0 :   printf( " | Contact Info V2        | %s |"        "  | Invalid    | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_CONTACT_INFO_V2 ) ] ), fmt_count( buf2, gossip_metrics[ MIDX( GAUGE, GOSSIP, PING_TRACKER_COUNT_INVALID ) ] ) );
     543           0 :   printf( " | Vote                   | %s |"        "  | Valid      | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_VOTE ) ] ),            fmt_count( buf2, gossip_metrics[ MIDX( GAUGE, GOSSIP, PING_TRACKER_COUNT_VALID ) ] ) );
     544           0 :   printf( " | Lowest Slot            | %s |"        "  | Refreshing | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_LOWEST_SLOT ) ] ),     fmt_count( buf2, gossip_metrics[ MIDX( GAUGE, GOSSIP, PING_TRACKER_COUNT_VALID_REFRESHING ) ] ) );
     545           0 :   printf( " | Snapshot Hashes        | %s |"        "  +------------+--------------+\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_SNAPSHOT_HASHES ) ] ) );
     546           0 :   printf( " | Accounts Hashes        | %s |"        "  +------------------------+--------------+\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_ACCOUNTS_HASHES ) ] ) );
     547           0 :   printf( " | Inc Snapshot Hashes    | %s |"        "  | Contact Info Events    | Count        |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_INCREMENTAL_SNAPSHOT_HASHES ) ] ) );
     548           0 :   printf( " | Epoch Slots            | %s |"        "  +------------------------+--------------+\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_EPOCH_SLOTS ) ] ) );
     549           0 :   printf( " | Version V1             | %s |"        "  | Unrecognized Socket    | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_VERSION_V1 ) ] ), fmt_count( buf2, 0UL ) );
     550           0 :   printf( " | Version V2             | %s |"        "  | IPv6 Address           | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_VERSION_V2 ) ] ), fmt_count( buf2, 0UL ) );
     551           0 :   printf( " | Node Instance          | %s |"        "  +------------------------+--------------+\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_NODE_INSTANCE ) ] ) );
     552           0 :   printf( " | Duplicate Shred        | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_DUPLICATE_SHRED ) ] ) );
     553           0 :   printf( " | Restart Last Voted     | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_RESTART_LAST_VOTED_FORK_SLOTS ) ] ) );
     554           0 :   printf( " | Restart Heaviest       | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_RESTART_HEAVIEST_FORK ) ] ) );
     555           0 :   printf( " +------------------------+--------------+\n\n" );
     556             : 
     557           0 : #define DIFFX(METRIC) gossip_metrics[ MIDX( COUNTER, TILE, METRIC ) ] - gossip_prev[ MIDX( COUNTER, TILE, METRIC ) ]
     558           0 :   ulong hkeep_ticks = DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_HOUSEKEEPING) + DIFFX(REGIME_DURATION_NANOS_PROCESSING_HOUSEKEEPING) + DIFFX(REGIME_DURATION_NANOS_BACKPRESSURE_HOUSEKEEPING);
     559           0 :   ulong busy_ticks = DIFFX(REGIME_DURATION_NANOS_PROCESSING_PREFRAG) + DIFFX(REGIME_DURATION_NANOS_PROCESSING_POSTFRAG ) + DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_PREFRAG);
     560           0 :   ulong caught_up_ticks = DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG);
     561           0 :   ulong backpressure_ticks = DIFFX(REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG);
     562           0 :   ulong total_ticks = hkeep_ticks + busy_ticks + caught_up_ticks + backpressure_ticks;
     563             : 
     564           0 :   printf( " Gossip Hkeep: %.1f %%  Busy: %.1f %%  Idle: %.1f %%  Backp: %0.1f %%\n",
     565           0 :           (double)hkeep_ticks/(double)total_ticks*100.0,
     566           0 :           (double)busy_ticks/(double)total_ticks*100.0,
     567           0 :           (double)caught_up_ticks/(double)total_ticks*100.0,
     568           0 :           (double)backpressure_ticks/(double)total_ticks*100.0 );
     569           0 : #undef DIFFX
     570             : 
     571             :   /* Aggregate gossvf performance metrics across all tiles */
     572           0 :   ulong gossvf_hkeep_ticks = 0UL, gossvf_busy_ticks = 0UL, gossvf_caught_up_ticks = 0UL, gossvf_backpressure_ticks = 0UL;
     573             : 
     574           0 :   for( ulong i = 0UL; i < ctx->gossvf.tile_count; i++ ) {
     575           0 :     volatile ulong * metrics  = ctx->gossvf.metrics[i];
     576           0 :     ulong * prev_metrics      = ctx->gossvf.prev_metrics[i];
     577             : 
     578           0 : #define DIFFX(METRIC) metrics[ MIDX( COUNTER, TILE, METRIC ) ] - prev_metrics[ MIDX( COUNTER, TILE, METRIC ) ]
     579           0 :     gossvf_hkeep_ticks        += DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_HOUSEKEEPING) + DIFFX(REGIME_DURATION_NANOS_PROCESSING_HOUSEKEEPING) + DIFFX(REGIME_DURATION_NANOS_BACKPRESSURE_HOUSEKEEPING);
     580           0 :     gossvf_busy_ticks         += DIFFX(REGIME_DURATION_NANOS_PROCESSING_PREFRAG) + DIFFX(REGIME_DURATION_NANOS_PROCESSING_POSTFRAG );
     581           0 :     gossvf_caught_up_ticks    += DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_PREFRAG) + DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG);
     582           0 :     gossvf_backpressure_ticks += DIFFX(REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG);
     583           0 : #undef DIFFX
     584           0 :   }
     585             : 
     586           0 :   ulong gossvf_total_ticks = gossvf_hkeep_ticks + gossvf_busy_ticks + gossvf_caught_up_ticks + gossvf_backpressure_ticks;
     587             : 
     588           0 :   printf( " Gossvf Hkeep: %.1f %%  Busy: %.1f %%  Idle: %.1f %%  Backp: %0.1f %% (%lu tiles)\n\n",
     589           0 :           gossvf_total_ticks > 0UL ? (double)gossvf_hkeep_ticks/(double)gossvf_total_ticks*100.0 : 0.0,
     590           0 :           gossvf_total_ticks > 0UL ? (double)gossvf_busy_ticks/(double)gossvf_total_ticks*100.0 : 0.0,
     591           0 :           gossvf_total_ticks > 0UL ? (double)gossvf_caught_up_ticks/(double)gossvf_total_ticks*100.0 : 0.0,
     592           0 :           gossvf_total_ticks > 0UL ? (double)gossvf_backpressure_ticks/(double)gossvf_total_ticks*100.0 : 0.0,
     593           0 :           ctx->gossvf.tile_count );
     594             : 
     595           0 :   printf( " +--------------+--------------+--------------+--------------+--------------+--------------+\n" );
     596           0 :   printf( " |              | Entries      | Capacity     | Utilization  | Evicted      | Expired      |\n" );
     597           0 :   printf( " +--------------+--------------+--------------+--------------+--------------+--------------+\n" );
     598           0 :   printf( " | Table Size   | %s | %s | %s | %s | %s |\n",
     599           0 :     fmt_count( buf1, total_crds ),
     600           0 :     fmt_count( buf2, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_CAPACITY ) ] ),
     601           0 :     fmt_pct( buf3, (double)total_crds / (double)gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_CAPACITY ) ] ),
     602           0 :     fmt_count( buf4, gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_EVICTED_COUNT ) ] ),
     603           0 :     fmt_count( buf5, gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_EXPIRED_COUNT ) ] ) );
     604           0 :   printf( " | Contact Info | %s | %s | %s | %s |          n/a |\n",
     605           0 :     fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_CONTACT_INFO_V2 ) ] ),
     606           0 :     fmt_count( buf2, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PEER_CAPACITY ) ] ),
     607           0 :     fmt_pct( buf3, (double)gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_CONTACT_INFO_V2 ) ] / (double)gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PEER_CAPACITY ) ] ),
     608           0 :     fmt_count( buf4, gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_PEER_EVICTED_COUNT ) ] ) );
     609           0 :   printf( " | Purged       | %s | %s | %s | %s | %s |\n",
     610           0 :     fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PURGED_COUNT ) ] ),
     611           0 :     fmt_count( buf2, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PURGED_CAPACITY ) ] ),
     612           0 :     fmt_pct( buf3, (double)gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PURGED_COUNT ) ] / (double)gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PURGED_CAPACITY ) ] ),
     613           0 :     fmt_count( buf4, gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_PURGED_EVICTED_COUNT ) ] ),
     614           0 :     fmt_count( buf5, gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_PURGED_EXPIRED_COUNT ) ] ) );
     615           0 :   printf( " +--------------+--------------+--------------+--------------+--------------+--------------+\n\n" );
     616             : 
     617           0 :   rx_deltas_t deltas = rx_deltas_aggregated( gossip_metrics, gossip_prev, &ctx->gossvf );
     618             : 
     619           0 :   printf( " +--------------------------------------------------------------------------+--------------+\n" );
     620           0 :   printf( " |              | RX count     | RX drops     | TX count     | RX bits      | TX bits      |\n" );
     621           0 :   printf( " +--------------+--------------+--------------+--------------+--------------+--------------+\n" );
     622           0 :   printf( " | Pull Request | %s | %s | %s | %s | %s |\n", fmt_count( buf1, deltas.pull_request_rx ), fmt_count( buf2, deltas.pull_request_rx_drop ),  fmt_count( buf3, deltas.pull_request_tx ),  fmt_bytes( buf4, deltas.pull_request_rx_bytes ),  fmt_bytes( buf5, deltas.pull_request_tx_bytes ) );
     623           0 :   printf( " | Pull Response| %s | %s | %s | %s | %s |\n", fmt_count( buf1, deltas.pull_response_rx), fmt_count( buf2, deltas.pull_response_rx_drop ), fmt_count( buf3, deltas.pull_response_tx ), fmt_bytes( buf4, deltas.pull_response_rx_bytes ), fmt_bytes( buf5, deltas.pull_response_tx_bytes ) );
     624           0 :   printf( " | Push         | %s | %s | %s | %s | %s |\n", fmt_count( buf1, deltas.push_rx ),         fmt_count( buf2, deltas.push_rx_drop ),          fmt_count( buf3, deltas.push_tx ),          fmt_bytes( buf4, deltas.push_rx_bytes ),          fmt_bytes( buf5, deltas.push_tx_bytes ) );
     625           0 :   printf( " | Prune        | %s | %s | %s | %s | %s |\n", fmt_count( buf1, deltas.prune_rx ),        fmt_count( buf2, deltas.prune_rx_drop ),         fmt_count( buf3, deltas.prune_tx ),         fmt_bytes( buf4, deltas.prune_rx_bytes ),         fmt_bytes( buf5, deltas.prune_tx_bytes ) );
     626           0 :   printf( " | Ping         | %s | %s | %s | %s | %s |\n", fmt_count( buf1, deltas.ping_rx ),         fmt_count( buf2, deltas.ping_rx_drop ),          fmt_count( buf3, deltas.ping_tx ),          fmt_bytes( buf4, deltas.ping_rx_bytes ),          fmt_bytes( buf5, deltas.ping_tx_bytes ) );
     627           0 :   printf( " | Pong         | %s | %s | %s | %s | %s |\n", fmt_count( buf1, deltas.pong_rx ),         fmt_count( buf2, deltas.pong_rx_drop ),          fmt_count( buf3, deltas.pong_tx ),          fmt_bytes( buf4, deltas.pong_rx_bytes ),          fmt_bytes( buf5, deltas.pong_tx_bytes ) );
     628           0 :   printf( " +--------------+--------------+--------------+--------------+--------------+--------------+\n\n" );
     629             : 
     630             :   /* Snapshot current metrics as previous for next render */
     631           0 :   for( ulong i=0UL; i<FD_METRICS_TOTAL_SZ/sizeof(ulong); i++ ) gossip_prev[ i ] = gossip_metrics[ i ];
     632             : 
     633           0 :   for( ulong tile_idx = 0UL; tile_idx < ctx->gossvf.tile_count; tile_idx++ ) {
     634           0 :     for( ulong i=0UL; i<FD_METRICS_TOTAL_SZ/sizeof(ulong); i++ ) {
     635           0 :       ctx->gossvf.prev_metrics[tile_idx][ i ] = ctx->gossvf.metrics[tile_idx][ i ];
     636           0 :     }
     637           0 :   }
     638           0 : }

Generated by: LCOV version 1.14