LCOV - code coverage report
Current view: top level - app/firedancer-dev/commands - gossip.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 896 0.0 %
Date: 2025-12-07 04:58:33 Functions: 0 15 0.0 %

          Line data    Source code
       1             : #include "../../shared/commands/configure/configure.h"
       2             : #include "../../shared/commands/run/run.h" /* initialize_workspaces */
       3             : #include "../../shared/fd_config.h" /* config_t */
       4             : #include "../../../disco/topo/fd_cpu_topo.h" /* fd_topo_cpus */
       5             : #include "../../../disco/topo/fd_topob.h"
       6             : #include "../../../disco/net/fd_net_tile.h" /* fd_topos_net_tiles */
       7             : #include "../../../disco/metrics/fd_metrics.h"
       8             : #include "../../../discof/gossip/fd_gossip_tile.h"
       9             : #include "../../../flamenco/gossip/fd_gossip_private.h"
      10             : #include "../../../util/pod/fd_pod_format.h"
      11             : #include "../../../util/net/fd_ip4.h" /* fd_cstr_to_ip4_addr */
      12             : #include "../../../util/clock/fd_clock.h"
      13             : 
      14             : #include "core_subtopo.h"
      15             : #include "gossip.h"
      16             : 
      17             : #include <stdio.h> /* printf */
      18             : #include <stdlib.h>
      19             : #include <unistd.h> /* isatty */
      20             : #include <sys/ioctl.h>
      21             : 
      22             : extern fd_topo_obj_callbacks_t * CALLBACKS[];
      23             : 
      24             : fd_topo_run_tile_t
      25             : fdctl_tile_run( fd_topo_tile_t const * tile );
      26             : 
      27             : static void
      28           0 : gossip_cmd_topo( config_t * config ) {
      29             : 
      30             :   /* Disable non-gossip listen ports */
      31           0 :   config->tiles.shred.shred_listen_port = 0U;
      32           0 :   config->tiles.quic.quic_transaction_listen_port = 0U;
      33           0 :   config->tiles.quic.regular_transaction_listen_port = 0U;
      34           0 :   config->tiles.repair.repair_intake_listen_port = 0U;
      35           0 :   config->tiles.repair.repair_serve_listen_port = 0U;
      36           0 :   config->tiles.send.send_src_port = 0U;
      37             : 
      38           0 :   static ulong tile_to_cpu[ FD_TILE_MAX ] = {0}; /* TODO */
      39             : 
      40           0 :   ulong net_tile_cnt = config->layout.net_tile_count;
      41             : 
      42             :   /* Reset topology from scratch */
      43           0 :   fd_topo_t * topo = &config->topo;
      44           0 :   fd_topob_new( &config->topo, config->name );
      45           0 :   topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
      46             : 
      47           0 :   fd_core_subtopo(   config, tile_to_cpu );
      48           0 :   fd_gossip_subtopo( config, tile_to_cpu );
      49             : 
      50           0 :   fd_topob_tile_in( topo, "gossip", 0UL, "metric_in", "sign_gossip",  0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
      51           0 :   for( ulong i=0UL; i<net_tile_cnt; i++ ) fd_topos_net_tile_finish( topo, i );
      52           0 :   fd_topob_auto_layout( topo, 0 );
      53           0 :   fd_topob_finish( topo, CALLBACKS );
      54           0 : }
      55             : 
      56             : void
      57           0 : fd_gossip_subtopo( config_t * config, ulong tile_to_cpu[ FD_TILE_MAX ] FD_PARAM_UNUSED ) {
      58           0 :   fd_topo_t * topo = &config->topo;
      59             : 
      60           0 :   ulong gossvf_tile_count = config->firedancer.layout.gossvf_tile_count;
      61           0 :   ulong net_tile_cnt = config->layout.net_tile_count;
      62             : 
      63           0 :   static char* const tiles_to_add[] = {
      64           0 :     "gossvf",
      65           0 :     "ipecho",
      66           0 :     "gossip",
      67           0 :   };
      68           0 :   for( int i=0; i<3; ++i) FD_TEST( fd_topo_find_tile( topo, tiles_to_add[i], 0UL ) == ULONG_MAX );
      69             : 
      70           0 :   fd_topob_wksp( topo, "gossip" );
      71           0 :   fd_topo_tile_t * gossip_tile = fd_topob_tile( topo, "gossip", "gossip", "metric_in", 0UL, 0, 1 /* uses_keyswitch */ );
      72           0 :   strncpy( gossip_tile->gossip.identity_key_path, config->paths.identity_key, sizeof(gossip_tile->gossip.identity_key_path) );
      73           0 :   gossip_tile->gossip.entrypoints_cnt        = config->gossip.entrypoints_cnt;
      74           0 :   for( ulong i=0UL; i<config->gossip.entrypoints_cnt; i++ ) {
      75           0 :     gossip_tile->gossip.entrypoints[ i ] = config->gossip.resolved_entrypoints[ i ];
      76           0 :   }
      77           0 :   gossip_tile->gossip.ip_addr              = config->net.ip_addr;
      78           0 :   gossip_tile->gossip.shred_version        = config->consensus.expected_shred_version;
      79           0 :   gossip_tile->gossip.max_entries          = config->tiles.gossip.max_entries;
      80           0 :   gossip_tile->gossip.ports.gossip         = config->gossip.port;
      81           0 :   gossip_tile->gossip.ports.repair         = 0;
      82           0 :   gossip_tile->gossip.ports.tpu            = 0;
      83           0 :   gossip_tile->gossip.ports.tpu_quic       = 0;
      84           0 :   gossip_tile->gossip.ports.tvu            = 0;
      85           0 :   gossip_tile->gossip.ports.tvu_quic       = 0;
      86           0 :   gossip_tile->gossip.boot_timestamp_nanos = config->boot_timestamp_nanos;
      87             : 
      88           0 :   fd_topob_wksp( topo, "gossvf" );
      89           0 :   for( ulong i=0UL; i<gossvf_tile_count; i++ ) {
      90           0 :     fd_topo_tile_t * gossvf_tile = fd_topob_tile( topo, "gossvf", "gossvf", "metric_in", 0UL, 0, 1 );
      91           0 :     strncpy( gossvf_tile->gossvf.identity_key_path, config->paths.identity_key, sizeof(gossvf_tile->gossvf.identity_key_path) );
      92           0 :     gossvf_tile->gossvf.tcache_depth = 1UL<<22UL;
      93           0 :     gossvf_tile->gossvf.shred_version = config->consensus.expected_shred_version;
      94           0 :     gossvf_tile->gossvf.allow_private_address = config->development.gossip.allow_private_address;
      95           0 :     gossvf_tile->gossvf.entrypoints_cnt = config->gossip.entrypoints_cnt;
      96           0 :     gossvf_tile->gossvf.boot_timestamp_nanos = config->boot_timestamp_nanos;
      97           0 :     for( ulong i=0UL; i<config->gossip.entrypoints_cnt; i++ ) {
      98           0 :       gossvf_tile->gossvf.entrypoints[ i ] = config->gossip.resolved_entrypoints[ i ];
      99           0 :     }
     100           0 :   }
     101           0 :   for( ulong i=0UL; i<net_tile_cnt; i++ ) {
     102           0 :     fd_topos_net_rx_link( topo, "net_gossvf", i, config->net.ingress_buffer_size );
     103           0 :   }
     104           0 :   for( ulong i=0UL; i<gossvf_tile_count; i++ ) {
     105           0 :     for( ulong j=0UL; j<net_tile_cnt; j++ ) {
     106           0 :       fd_topob_tile_in( topo, "gossvf", i, "metric_in", "net_gossvf", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     107           0 :     }
     108           0 :   }
     109             : 
     110           0 :   fd_topob_wksp( topo, "gossip_net" );
     111           0 :   fd_topob_link( topo, "gossip_net", "gossip_net", 65536*4UL, FD_NET_MTU, 1UL );
     112           0 :   fd_topos_tile_in_net( topo, "metric_in", "gossip_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     113           0 :   fd_topob_tile_out( topo, "gossip", 0UL, "gossip_net", 0UL );
     114             : 
     115           0 :   fd_topob_wksp( topo, "ipecho" );
     116           0 :   fd_topo_tile_t * ipecho_tile = fd_topob_tile( topo, "ipecho", "ipecho", "metric_in", 0UL, 0, 0 );
     117           0 :   ipecho_tile->ipecho.expected_shred_version = config->consensus.expected_shred_version;
     118           0 :   ipecho_tile->ipecho.bind_address = config->net.ip_addr;
     119           0 :   ipecho_tile->ipecho.bind_port = config->gossip.port;
     120           0 :   ipecho_tile->ipecho.entrypoints_cnt = config->gossip.entrypoints_cnt;
     121           0 :   for( ulong i=0UL; i<config->gossip.entrypoints_cnt; i++ ) {
     122           0 :     ipecho_tile->ipecho.entrypoints[ i ] = config->gossip.resolved_entrypoints[ i ];
     123           0 :   }
     124             : 
     125           0 :   fd_topob_wksp( topo, "ipecho_out" );
     126           0 :   fd_topob_link( topo, "ipecho_out", "ipecho_out", 4UL, 0UL, 1UL );
     127           0 :   fd_topob_tile_out( topo, "ipecho", 0UL, "ipecho_out", 0UL );
     128             : 
     129           0 :   for( ulong i=0UL; i<gossvf_tile_count; i++ ) {
     130           0 :     fd_topob_tile_in( topo, "gossvf", i, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     131           0 :   }
     132           0 :   fd_topob_tile_in( topo, "gossip", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     133             : 
     134           0 :   fd_topob_wksp( topo, "gossvf_gossi" );
     135           0 :   fd_topob_wksp( topo, "gossip_gossv" );
     136           0 :   fd_topob_wksp( topo, "gossip_out" );
     137             : 
     138           0 :   fd_topob_link(     topo, "gossip_gossv", "gossip_gossv", 65536UL*4, sizeof(fd_gossip_ping_update_t), 1UL );
     139           0 :   fd_topob_tile_out( topo, "gossip", 0UL, "gossip_gossv", 0UL );
     140             : 
     141           0 :   fd_topob_link( topo, "gossip_out", "gossip_out", 65536UL*4, sizeof(fd_gossip_update_message_t), 1UL );
     142           0 :   fd_topob_tile_out( topo, "gossip", 0UL, "gossip_out", 0UL );
     143           0 :   for( ulong i=0UL; i<gossvf_tile_count; i++ ) {
     144           0 :     fd_topob_link(     topo, "gossvf_gossi", "gossvf_gossi", 65536UL*4, sizeof(fd_gossip_view_t)+FD_NET_MTU, 1UL );
     145           0 :     fd_topob_tile_out( topo, "gossvf", i, "gossvf_gossi", i );
     146           0 :     fd_topob_tile_in(  topo, "gossip", 0UL, "metric_in", "gossvf_gossi", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     147             : 
     148             :     /* Only one link_kind for gossip_out broadcast link */
     149           0 :     fd_topob_tile_in( topo, "gossvf", i, "metric_in", "gossip_gossv", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     150           0 :     fd_topob_tile_in( topo, "gossvf", i, "metric_in", "gossip_out",   0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     151           0 :   }
     152             : 
     153           0 :   fd_topob_wksp( topo, "gossip_sign"  );
     154           0 :   fd_topob_link( topo, "gossip_sign", "gossip_sign", 128UL, 2048UL, 1UL );
     155           0 :   fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "gossip_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     156           0 :   fd_topob_wksp( topo, "sign_gossip"  );
     157           0 :   fd_topob_link( topo, "sign_gossip", "sign_gossip", 128UL, 64UL, 1UL );
     158           0 :   fd_topob_tile_out( topo, "sign", 0UL, "sign_gossip", 0UL );
     159           0 :   fd_topob_tile_out( topo, "gossip", 0UL, "gossip_sign", 0UL );
     160           0 : }
     161             : 
     162             : static args_t
     163           0 : configure_args( void ) {
     164           0 :   args_t args = {
     165           0 :     .configure.command = CONFIGURE_CMD_INIT,
     166           0 :   };
     167             : 
     168           0 :   ulong stage_idx = 0UL;
     169           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_hugetlbfs;
     170           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_sysctl;
     171           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_bonding;
     172           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_ethtool_channels;
     173           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_ethtool_offloads;
     174           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_ethtool_loopback;
     175           0 :   args.configure.stages[ stage_idx++ ] = NULL;
     176             : 
     177           0 :   return args;
     178           0 : }
     179             : 
     180             : void
     181             : gossip_cmd_perm( args_t *         args FD_PARAM_UNUSED,
     182             :                  fd_cap_chk_t *   chk,
     183           0 :                  config_t const * config ) {
     184           0 :   args_t c_args = configure_args();
     185           0 :   configure_cmd_perm( &c_args, chk, config );
     186           0 :   run_cmd_perm( NULL, chk, config );
     187           0 : }
     188             : 
     189             : static char *
     190           0 : fmt_count( char buf[ static 64 ], ulong count ) {
     191           0 :   char tmp[ 64 ];
     192           0 :   if( FD_LIKELY( count<1000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%lu", count ) );
     193           0 :   else if( FD_LIKELY( count<1000000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f K", (double)count/1000.0 ) );
     194           0 :   else if( FD_LIKELY( count<1000000000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f M", (double)count/1000000.0 ) );
     195             : 
     196           0 :   FD_TEST( fd_cstr_printf_check( buf, 64UL, NULL, "%12s", tmp ) );
     197           0 :   return buf;
     198           0 : }
     199             : 
     200             : static char *
     201           0 : fmt_bytes( char buf[ static 64 ], ulong bytes ) {
     202           0 :   char tmp[ 64 ];
     203           0 :   if( FD_LIKELY( 8UL*bytes<1000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%lu bits", 8UL*bytes ) );
     204           0 :   else if( FD_LIKELY( 8UL*bytes<1000000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f Kbit", (double)(8UL*bytes)/1000.0 ) );
     205           0 :   else if( FD_LIKELY( 8UL*bytes<1000000000UL ) ) FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f Mbit", (double)(8UL*bytes)/1000000.0 ) );
     206           0 :   else FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f Gbit", (double)(8UL*bytes)/1000000000.0 ) );
     207             : 
     208           0 :   FD_TEST( fd_cstr_printf_check( buf, 64UL, NULL, "%12s", tmp ) );
     209           0 :   return buf;
     210           0 : }
     211             : 
     212             : static char *
     213           0 : fmt_pct( char buf[ static 64 ], double pct ) {
     214           0 :   char tmp[ 64 ];
     215           0 :   FD_TEST( fd_cstr_printf_check( tmp, 64UL, NULL, "%.1f %%", 100.0*pct ) );
     216           0 :   FD_TEST( fd_cstr_printf_check( buf, 64UL, NULL, "%12s", tmp ) );
     217           0 :   return buf;
     218           0 : }
     219             : 
     220             : struct rx_deltas {
     221             :   ulong pull_request_rx;
     222             :   ulong pull_request_rx_drop;
     223             :   ulong pull_request_rx_bytes;
     224             :   ulong pull_request_tx;
     225             :   ulong pull_request_tx_bytes;
     226             : 
     227             :   ulong pull_response_rx;
     228             :   ulong pull_response_rx_drop;
     229             :   ulong pull_response_rx_bytes;
     230             :   ulong pull_response_tx;
     231             :   ulong pull_response_tx_bytes;
     232             : 
     233             :   ulong push_rx;
     234             :   ulong push_rx_drop;
     235             :   ulong push_rx_bytes;
     236             :   ulong push_tx;
     237             :   ulong push_tx_bytes;
     238             : 
     239             :   ulong prune_rx;
     240             :   ulong prune_rx_drop;
     241             :   ulong prune_rx_bytes;
     242             :   ulong prune_tx;
     243             :   ulong prune_tx_bytes;
     244             : 
     245             :   ulong ping_rx;
     246             :   ulong ping_rx_drop;
     247             :   ulong ping_rx_bytes;
     248             :   ulong ping_tx;
     249             :   ulong ping_tx_bytes;
     250             : 
     251             :   ulong pong_rx;
     252             :   ulong pong_rx_drop;
     253             :   ulong pong_rx_bytes;
     254             :   ulong pong_tx;
     255             :   ulong pong_tx_bytes;
     256             : };
     257             : 
     258             : typedef struct rx_deltas rx_deltas_t;
     259             : 
     260             : /* Data structures for handling multiple gossvf tiles */
     261             : typedef struct {
     262             :   ulong                tile_count;
     263             :   fd_topo_tile_t **    tiles;
     264             :   volatile ulong **    metrics;
     265             :   ulong **             prev_metrics;
     266             :   volatile ulong **    net_links;
     267             : } gossvf_tiles_t;
     268             : 
     269             : /* Collect all gossvf tiles from topology */
     270             : static gossvf_tiles_t
     271           0 : collect_gossvf_tiles( fd_topo_t * topo ) {
     272           0 :   gossvf_tiles_t tiles = {0};
     273           0 :   tiles.tile_count = fd_topo_tile_name_cnt( topo, "gossvf" );
     274             : 
     275           0 :   if( FD_UNLIKELY( tiles.tile_count == 0UL ) ) {
     276           0 :     FD_LOG_ERR(( "No gossvf tiles found in topology" ));
     277           0 :   }
     278             : 
     279             :   /* Allocate arrays for all tiles */
     280           0 :   tiles.tiles = aligned_alloc( 8UL, tiles.tile_count * sizeof(fd_topo_tile_t*) );
     281           0 :   FD_TEST( tiles.tiles );
     282           0 :   tiles.metrics = aligned_alloc( 8UL, tiles.tile_count * sizeof(volatile ulong*) );
     283           0 :   FD_TEST( tiles.metrics );
     284           0 :   tiles.prev_metrics = aligned_alloc( 8UL, tiles.tile_count * sizeof(ulong*) );
     285           0 :   FD_TEST( tiles.prev_metrics );
     286           0 :   tiles.net_links = aligned_alloc( 8UL, tiles.tile_count * sizeof(volatile ulong*) );
     287           0 :   FD_TEST( tiles.net_links );
     288             : 
     289             :   /* Find and populate all gossvf tiles */
     290           0 :   for( ulong i = 0UL; i < tiles.tile_count; i++ ) {
     291           0 :     ulong tile_idx = fd_topo_find_tile( topo, "gossvf", i );
     292           0 :     FD_TEST( tile_idx != ULONG_MAX );
     293             : 
     294           0 :     tiles.tiles[i] = &topo->tiles[ tile_idx ];
     295           0 :     tiles.metrics[i] = fd_metrics_tile( tiles.tiles[i]->metrics );
     296           0 :     FD_TEST( tiles.metrics[i] );
     297             : 
     298           0 :     tiles.prev_metrics[i] = aligned_alloc( 8UL, FD_METRICS_TOTAL_SZ );
     299           0 :     FD_TEST( tiles.prev_metrics[i] );
     300           0 :     memset( tiles.prev_metrics[i], 0, FD_METRICS_TOTAL_SZ );
     301             : 
     302           0 :     tiles.net_links[i] = fd_metrics_link_in( tiles.tiles[i]->metrics, 0UL );
     303           0 :     FD_TEST( tiles.net_links[i] );
     304           0 :   }
     305             : 
     306           0 :   return tiles;
     307           0 : }
     308             : 
     309             : /* Aggregate specific GOSSVF counter metrics that make sense to sum */
     310             : static ulong
     311           0 : aggregate_gossvf_counter( gossvf_tiles_t * tiles, ulong metric_idx ) {
     312           0 :   ulong total = 0UL;
     313           0 :   for( ulong i = 0UL; i < tiles->tile_count; i++ ) {
     314           0 :     total += tiles->metrics[i][metric_idx];
     315           0 :   }
     316           0 :   return total;
     317           0 : }
     318             : 
     319             : /* Aggregate specific GOSSVF previous counter metrics */
     320             : static ulong
     321           0 : aggregate_gossvf_prev_counter( gossvf_tiles_t * tiles, ulong metric_idx ) {
     322           0 :   ulong total = 0UL;
     323           0 :   for( ulong i = 0UL; i < tiles->tile_count; i++ ) {
     324           0 :     total += tiles->prev_metrics[i][metric_idx];
     325           0 :   }
     326           0 :   return total;
     327           0 : }
     328             : 
     329             : /* Enhanced rx_deltas function that works with multiple gossvf tiles */
     330             : static rx_deltas_t
     331             : rx_deltas_aggregated( volatile ulong * gossip_metrics,
     332             :                      ulong *          gossip_prev,
     333           0 :                      gossvf_tiles_t * gossvf_tiles ) {
     334           0 :   rx_deltas_t deltas;
     335             : 
     336             :   /* Aggregate pull request metrics across all gossvf tiles */
     337           0 :   ulong pull_request_rx_current =
     338           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_REQUEST ) ) +
     339           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     340           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     341           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     342           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     343           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     344           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) );
     345             : 
     346           0 :   ulong pull_request_rx_prev =
     347           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_REQUEST ) ) +
     348           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     349           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     350           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     351           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     352           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     353           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) );
     354             : 
     355           0 :   deltas.pull_request_rx = pull_request_rx_current - pull_request_rx_prev;
     356             : 
     357             :   /* Continue with other metrics... (truncated for brevity, but same pattern) */
     358           0 :   deltas.pull_request_rx_drop =
     359           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     360           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     361           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     362           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     363           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     364           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) )) -
     365           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     366           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     367           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     368           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     369           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     370           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ));
     371             : 
     372             :   /* TX metrics come from gossip tile (unchanged) */
     373           0 :   deltas.pull_request_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_REQUEST ) ] -
     374           0 :                            gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_REQUEST ) ];
     375           0 :   deltas.pull_request_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_REQUEST ) ] -
     376           0 :                                  gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_REQUEST ) ];
     377             : 
     378             :   /* RX bytes aggregated across tiles */
     379           0 :   deltas.pull_request_rx_bytes =
     380           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_REQUEST ) ) +
     381           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     382           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     383           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     384           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     385           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     386           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SHRED_VERSION ) )) -
     387           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_REQUEST ) ) +
     388           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ) +
     389           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_LOOPBACK ) ) +
     390           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_INACTIVE ) ) +
     391           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_WALLCLOCK ) ) +
     392           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SIGNATURE ) ) +
     393           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SHRED_VERSION ) ));
     394             : 
     395             :   /* For brevity, I'll implement the remaining metrics with the same pattern */
     396             :   /* Pull response metrics */
     397           0 :   deltas.pull_response_rx =
     398           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) ) +
     399           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) )) -
     400           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) ) +
     401           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ));
     402             : 
     403           0 :   deltas.pull_response_rx_drop =
     404           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ) -
     405           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) );
     406             : 
     407           0 :   deltas.pull_response_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_RESPONSE ) ] -
     408           0 :                             gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_RESPONSE ) ];
     409           0 :   deltas.pull_response_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_RESPONSE ) ] -
     410           0 :                                   gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_RESPONSE ) ];
     411           0 :   deltas.pull_response_rx_bytes =
     412           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_RESPONSE ) ) +
     413           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) )) -
     414           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_RESPONSE ) ) +
     415           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ));
     416             : 
     417             :   /* Push metrics */
     418           0 :   deltas.push_rx =
     419           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) ) +
     420           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) )) -
     421           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) ) +
     422           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) ));
     423             : 
     424           0 :   deltas.push_rx_drop =
     425           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) ) -
     426           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) );
     427             : 
     428           0 :   deltas.push_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PUSH ) ] -
     429           0 :                    gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PUSH ) ];
     430           0 :   deltas.push_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PUSH ) ] -
     431           0 :                          gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PUSH ) ];
     432           0 :   deltas.push_rx_bytes =
     433           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PUSH ) ) +
     434           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PUSH_NO_VALID_CRDS ) )) -
     435           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PUSH ) ) +
     436           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PUSH_NO_VALID_CRDS ) ));
     437             : 
     438             :   /* Prune metrics */
     439           0 :   deltas.prune_rx =
     440           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PRUNE ) ) +
     441           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ) +
     442           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ) +
     443           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) )) -
     444           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PRUNE ) ) +
     445           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ) +
     446           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ) +
     447           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) ));
     448             : 
     449           0 :   deltas.prune_rx_drop =
     450           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ) +
     451           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ) +
     452           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) )) -
     453           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ) +
     454           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ) +
     455           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) ));
     456             : 
     457           0 :   deltas.prune_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PRUNE ) ] -
     458           0 :                     gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PRUNE ) ];
     459           0 :   deltas.prune_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PRUNE ) ] -
     460           0 :                           gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PRUNE ) ];
     461           0 :   deltas.prune_rx_bytes =
     462           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PRUNE ) ) +
     463           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_DESTINATION ) ) +
     464           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_WALLCLOCK ) ) +
     465           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_SIGNATURE ) )) -
     466           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PRUNE ) ) +
     467           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_DESTINATION ) ) +
     468           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_WALLCLOCK ) ) +
     469           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_SIGNATURE ) ));
     470             : 
     471             :   /* Ping metrics */
     472           0 :   deltas.ping_rx =
     473           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PING ) ) +
     474           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) )) -
     475           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PING ) ) +
     476           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) ));
     477             : 
     478           0 :   deltas.ping_rx_drop =
     479           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) ) -
     480           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) );
     481             : 
     482           0 :   deltas.ping_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PING ) ] -
     483           0 :                    gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PING ) ];
     484           0 :   deltas.ping_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PING ) ] -
     485           0 :                          gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PING ) ];
     486           0 :   deltas.ping_rx_bytes =
     487           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PING ) ) +
     488           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PING_SIGNATURE ) )) -
     489           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PING ) ) +
     490           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PING_SIGNATURE ) ));
     491             : 
     492             :   /* Pong metrics */
     493           0 :   deltas.pong_rx =
     494           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PONG ) ) +
     495           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) )) -
     496           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PONG ) ) +
     497           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) ));
     498             : 
     499           0 :   deltas.pong_rx_drop =
     500           0 :     aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) ) -
     501           0 :     aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) );
     502             : 
     503           0 :   deltas.pong_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PONG ) ] -
     504           0 :                    gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PONG ) ];
     505           0 :   deltas.pong_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PONG ) ] -
     506           0 :                          gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PONG ) ];
     507           0 :   deltas.pong_rx_bytes =
     508           0 :     (aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PONG ) ) +
     509           0 :      aggregate_gossvf_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PONG_SIGNATURE ) )) -
     510           0 :     (aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PONG ) ) +
     511           0 :      aggregate_gossvf_prev_counter( gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PONG_SIGNATURE ) ));
     512             : 
     513           0 :   return deltas;
     514           0 : }
     515             : /* Display detailed per-tile gossvf metrics */
     516             : FD_FN_UNUSED static void
     517           0 : display_gossvf_detailed( gossvf_tiles_t * tiles ) {
     518           0 :   printf("\n=== Detailed Per-Tile Gossvf Metrics ===\n");
     519           0 : 
     520           0 :   for( ulong i = 0UL; i < tiles->tile_count; i++ ) {
     521           0 :     printf("\n--- Gossvf Tile %lu ---\n", i);
     522           0 : 
     523           0 :     volatile ulong * metrics = tiles->metrics[i];
     524           0 :     ulong * prev_metrics = tiles->prev_metrics[i];
     525           0 : 
     526           0 :     /* Performance metrics for this tile */
     527           0 : #define DIFFX(METRIC) metrics[ MIDX( COUNTER, TILE, METRIC ) ] - prev_metrics[ MIDX( COUNTER, TILE, METRIC ) ]
     528           0 :     ulong hkeep_ticks = DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_HOUSEKEEPING) +
     529           0 :                         DIFFX(REGIME_DURATION_NANOS_PROCESSING_HOUSEKEEPING) +
     530           0 :                         DIFFX(REGIME_DURATION_NANOS_BACKPRESSURE_HOUSEKEEPING);
     531           0 :     ulong busy_ticks = DIFFX(REGIME_DURATION_NANOS_PROCESSING_PREFRAG) +
     532           0 :                        DIFFX(REGIME_DURATION_NANOS_PROCESSING_POSTFRAG);
     533           0 :     ulong caught_up_ticks = DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_PREFRAG) +
     534           0 :                             DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG);
     535           0 :     ulong backpressure_ticks = DIFFX(REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG);
     536           0 :     ulong total_ticks = hkeep_ticks + busy_ticks + caught_up_ticks + backpressure_ticks;
     537           0 : #undef DIFFX
     538           0 : 
     539           0 :     if( total_ticks > 0UL ) {
     540           0 :       printf("  Performance: Hkeep: %.1f %%  Busy: %.1f %%  Idle: %.1f %%  Backp: %.1f %%\n",
     541           0 :              (double)hkeep_ticks/(double)total_ticks*100.0,
     542           0 :              (double)busy_ticks/(double)total_ticks*100.0,
     543           0 :              (double)caught_up_ticks/(double)total_ticks*100.0,
     544           0 :              (double)backpressure_ticks/(double)total_ticks*100.0);
     545           0 :     }
     546           0 : 
     547           0 :     /* Message counts for this tile */
     548           0 :     printf("  Pull Request RX: %lu (Success: %lu, Drops: %lu)\n",
     549           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_REQUEST ) ] +
     550           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ] +
     551           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ] +
     552           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ] +
     553           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ] +
     554           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ] +
     555           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ],
     556           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_REQUEST ) ],
     557           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ] +
     558           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ] +
     559           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ] +
     560           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ] +
     561           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ] +
     562           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ]);
     563           0 : 
     564           0 :     printf("  Pull Response RX: %lu (Success: %lu, Drops: %lu)\n",
     565           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) ] +
     566           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ],
     567           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) ],
     568           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ]);
     569           0 : 
     570           0 :     printf("  Push RX: %lu (Success: %lu, Drops: %lu)\n",
     571           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) ] +
     572           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) ],
     573           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) ],
     574           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) ]);
     575           0 : 
     576           0 :     printf("  Prune RX: %lu (Success: %lu, Drops: %lu)\n",
     577           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PRUNE ) ] +
     578           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ] +
     579           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ] +
     580           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) ],
     581           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PRUNE ) ],
     582           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ] +
     583           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ] +
     584           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) ]);
     585           0 : 
     586           0 :     printf("  Ping RX: %lu (Success: %lu, Drops: %lu)\n",
     587           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PING ) ] +
     588           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) ],
     589           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PING ) ],
     590           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) ]);
     591           0 : 
     592           0 :     printf("  Pong RX: %lu (Success: %lu, Drops: %lu)\n",
     593           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PONG ) ] +
     594           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) ],
     595           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PONG ) ],
     596           0 :            metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) ]);
     597           0 :   }
     598           0 : 
     599           0 :   printf("\n=== End Detailed View ===\n");
     600           0 : }
     601             : 
     602             : 
     603             : FD_FN_UNUSED static rx_deltas_t
     604             : rx_deltas( volatile ulong * gossip_metrics,
     605             :            ulong *          gossip_prev,
     606             :            volatile ulong * gossvf_metrics,
     607           0 :            ulong *          gossvf_prev ) {
     608           0 :   rx_deltas_t deltas;
     609           0 : 
     610           0 :   deltas.pull_request_rx = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_REQUEST ) ] +
     611           0 :                            gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ] +
     612           0 :                            gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ] +
     613           0 :                            gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ] +
     614           0 :                            gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ] +
     615           0 :                            gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ] +
     616           0 :                            gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ] -
     617           0 :                            gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_REQUEST ) ] -
     618           0 :                            gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ] -
     619           0 :                            gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ] -
     620           0 :                            gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ] -
     621           0 :                            gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ] -
     622           0 :                            gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ] -
     623           0 :                            gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ];
     624           0 :   deltas.pull_request_rx_drop = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ] +
     625           0 :                                 gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ] +
     626           0 :                                 gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ] +
     627           0 :                                 gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ] +
     628           0 :                                 gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ] +
     629           0 :                                 gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ] -
     630           0 :                                 gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ] -
     631           0 :                                 gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) ] -
     632           0 :                                 gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) ] -
     633           0 :                                 gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) ] -
     634           0 :                                 gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) ] -
     635           0 :                                 gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) ];
     636           0 :   deltas.pull_request_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_REQUEST ) ] -
     637           0 :                            gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_REQUEST ) ];
     638           0 :   deltas.pull_request_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_REQUEST ) ] -
     639           0 :                                  gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_REQUEST ) ];
     640           0 :   deltas.pull_request_rx_bytes = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_REQUEST ) ] +
     641           0 :                                  gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ] +
     642           0 :                                  gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_LOOPBACK ) ] +
     643           0 :                                  gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_INACTIVE ) ] +
     644           0 :                                  gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_WALLCLOCK ) ] +
     645           0 :                                  gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SIGNATURE ) ] +
     646           0 :                                  gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SHRED_VERSION ) ] -
     647           0 :                                  gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_REQUEST ) ] -
     648           0 :                                  gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) ] -
     649           0 :                                  gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_LOOPBACK ) ] -
     650           0 :                                  gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_INACTIVE ) ] -
     651           0 :                                  gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_WALLCLOCK ) ] -
     652           0 :                                  gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SIGNATURE ) ] -
     653           0 :                                  gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SHRED_VERSION ) ];
     654           0 : 
     655           0 :   deltas.pull_response_rx = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) ] +
     656           0 :                             gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ] -
     657           0 :                             gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) ] -
     658           0 :                             gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ];
     659           0 :   deltas.pull_response_rx_drop = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ] -
     660           0 :                                  gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ];
     661           0 :   deltas.pull_response_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_RESPONSE ) ] -
     662           0 :                             gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_RESPONSE ) ];
     663           0 :   deltas.pull_response_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_RESPONSE ) ] -
     664           0 :                                   gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_RESPONSE ) ];
     665           0 :   deltas.pull_response_rx_bytes = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_RESPONSE ) ] +
     666           0 :                                   gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ] -
     667           0 :                                   gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_RESPONSE ) ] -
     668           0 :                                   gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) ];
     669           0 : 
     670           0 :   deltas.push_rx = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) ] +
     671           0 :                    gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) ] -
     672           0 :                    gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) ] -
     673           0 :                    gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) ];
     674           0 :   deltas.push_rx_drop = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) ] -
     675           0 :                         gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) ];
     676           0 :   deltas.push_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PUSH ) ] -
     677           0 :                    gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PUSH ) ];
     678           0 :   deltas.push_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PUSH ) ] -
     679           0 :                          gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PUSH ) ];
     680           0 :   deltas.push_rx_bytes = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PUSH ) ] +
     681           0 :                          gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PUSH_NO_VALID_CRDS ) ] -
     682           0 :                          gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PUSH ) ] -
     683           0 :                          gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PUSH_NO_VALID_CRDS ) ];
     684           0 : 
     685           0 :   deltas.prune_rx = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PRUNE ) ] +
     686           0 :                     gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ] +
     687           0 :                     gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ] +
     688           0 :                     gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) ] -
     689           0 :                     gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PRUNE ) ] -
     690           0 :                     gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ] -
     691           0 :                     gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ] -
     692           0 :                     gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) ];
     693           0 :   deltas.prune_rx_drop = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ] +
     694           0 :                          gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ] +
     695           0 :                          gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) ] -
     696           0 :                          gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ] -
     697           0 :                          gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) ] -
     698           0 :                          gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) ];
     699           0 :   deltas.prune_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PRUNE ) ] -
     700           0 :                     gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PRUNE ) ];
     701           0 :   deltas.prune_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PRUNE ) ] -
     702           0 :                           gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PRUNE ) ];
     703           0 :   deltas.prune_rx_bytes = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PRUNE ) ] +
     704           0 :                           gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ] +
     705           0 :                           gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_WALLCLOCK ) ] +
     706           0 :                           gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_SIGNATURE ) ] -
     707           0 :                           gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PRUNE ) ] -
     708           0 :                           gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) ] -
     709           0 :                           gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_WALLCLOCK ) ] -
     710           0 :                           gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_SIGNATURE ) ];
     711           0 : 
     712           0 :   deltas.ping_rx = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PING ) ] +
     713           0 :                    gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) ] -
     714           0 :                    gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PING ) ] -
     715           0 :                    gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) ];
     716           0 :   deltas.ping_rx_drop = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) ] -
     717           0 :                         gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) ];
     718           0 :   deltas.ping_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PING ) ] -
     719           0 :                    gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PING ) ];
     720           0 :   deltas.ping_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PING ) ] -
     721           0 :                          gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PING ) ];
     722           0 :   deltas.ping_rx_bytes = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PING ) ] +
     723           0 :                          gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PING_SIGNATURE ) ] -
     724           0 :                          gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PING ) ] -
     725           0 :                          gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PING_SIGNATURE ) ];
     726           0 : 
     727           0 :   deltas.pong_rx = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PONG ) ] +
     728           0 :                    gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) ] -
     729           0 :                    gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PONG ) ] -
     730           0 :                    gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) ];
     731           0 :   deltas.pong_rx_drop = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) ] -
     732           0 :                         gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) ];
     733           0 :   deltas.pong_tx = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PONG ) ] -
     734           0 :                    gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PONG ) ];
     735           0 :   deltas.pong_tx_bytes = gossip_metrics[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PONG ) ] -
     736           0 :                          gossip_prev[ MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PONG ) ];
     737           0 :   deltas.pong_rx_bytes = gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PONG ) ] +
     738           0 :                          gossvf_metrics[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PONG_SIGNATURE ) ] -
     739           0 :                          gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PONG ) ] -
     740           0 :                          gossvf_prev[ MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PONG_SIGNATURE ) ];
     741           0 : 
     742           0 :   return deltas;
     743           0 : }
     744             : 
     745             : static void
     746             : gossip_args( int *    pargc,
     747             :              char *** pargv,
     748           0 :              args_t * args  ) {
     749           0 :   if( FD_UNLIKELY( fd_env_strip_cmdline_contains( pargc, pargv, "--help" ) ) ) {
     750           0 :     fputs(
     751           0 :       "\nUsage: firedancer-dev gossip [GLOBAL FLAGS] [FLAGS]\n"
     752           0 :       "\n"
     753           0 :       "Global Flags:\n"
     754           0 :       "  --mainnet            Use Solana mainnet-beta defaults\n"
     755           0 :       "  --testnet            Use Solana testnet defaults\n"
     756           0 :       "  --devnet             Use Solana devnet defaults\n"
     757           0 :       "\n"
     758           0 :       "Flags:\n"
     759           0 :       "  --max-entries <num>         Exit once we see <num> CRDS entries in table\n"
     760           0 :       "  --max-contact-infos <num>   Exit once we see <num> contact infos in table\n"
     761           0 :       "  --compact                   Use compact output format\n"
     762           0 :       "\n",
     763           0 :       stderr );
     764           0 :     exit( EXIT_SUCCESS );
     765           0 :   }
     766             : 
     767           0 :   args->gossip.max_entries  = fd_env_strip_cmdline_ulong   ( pargc, pargv, "--max-entries", NULL, ULONG_MAX );
     768           0 :   args->gossip.max_contact  = fd_env_strip_cmdline_ulong   ( pargc, pargv, "--max-contact-infos", NULL, ULONG_MAX );
     769           0 :   args->gossip.compact_mode = fd_env_strip_cmdline_contains( pargc, pargv, "--compact" );
     770           0 : }
     771             : 
     772             : void
     773             : gossip_cmd_fn( args_t *   args,
     774           0 :                config_t * config ) {
     775           0 :   (void)args;
     776             : 
     777           0 :   args_t c_args = configure_args();
     778           0 :   configure_cmd_fn( &c_args, config );
     779             : 
     780           0 :   run_firedancer_init( config, 1, 1 );
     781             : 
     782           0 :   int const is_xdp = ( 0==strcmp( config->net.provider, "xdp" ) );
     783           0 :   if( is_xdp ) fd_topo_install_xdp_simple( &config->topo, config->net.bind_address_parsed );
     784           0 :   fd_topo_join_workspaces( &config->topo, FD_SHMEM_JOIN_MODE_READ_WRITE );
     785           0 :   fd_topo_fill( &config->topo );
     786             : 
     787           0 :   ulong gossip_tile_idx = fd_topo_find_tile( &config->topo, "gossip", 0UL );
     788           0 :   FD_TEST( gossip_tile_idx!=ULONG_MAX );
     789           0 :   fd_topo_tile_t * gossip_tile = &config->topo.tiles[ gossip_tile_idx ];
     790             : 
     791             :   /* Collect all gossvf tiles instead of just the first one */
     792           0 :   gossvf_tiles_t gossvf_tiles = collect_gossvf_tiles( &config->topo );
     793           0 :   printf("Found %lu gossvf tiles\n", gossvf_tiles.tile_count);
     794             : 
     795           0 :   volatile ulong * gossip_metrics = fd_metrics_tile( gossip_tile->metrics );
     796           0 :   FD_TEST( gossip_metrics );
     797             : 
     798           0 :   ulong const net_tile_cnt = config->layout.net_tile_count;
     799           0 :   volatile ulong const ** net_metrics = aligned_alloc( 8UL, net_tile_cnt * sizeof(volatile ulong const *) );
     800           0 :   FD_TEST( net_metrics );
     801           0 :   for( ulong i=0UL; i<net_tile_cnt; i++ ) {
     802           0 :     ulong net_tile_idx = fd_topo_find_tile( &config->topo, is_xdp ? "net" : "sock", i );
     803           0 :     FD_TEST( net_tile_idx!=ULONG_MAX );
     804           0 :     fd_topo_tile_t * net_tile = &config->topo.tiles[ net_tile_idx ];
     805           0 :     net_metrics[ i ] = fd_metrics_tile( net_tile->metrics );
     806           0 :     FD_TEST( net_metrics[ i ] );
     807           0 :   }
     808             : 
     809             :   /* FIXME allow running sandboxed/multiprocess */
     810           0 :   fd_topo_run_single_process( &config->topo, 2, config->uid, config->gid, fdctl_tile_run );
     811             : 
     812             :   /* Use the first gossvf tile's net link for overrun monitoring */
     813           0 :   volatile ulong * net0_link = gossvf_tiles.net_links[0];
     814           0 :   FD_TEST( net0_link );
     815             : 
     816           0 :   ulong * gossip_prev = aligned_alloc( 8UL, FD_METRICS_TOTAL_SZ );
     817           0 :   FD_TEST( gossip_prev );
     818           0 :   memset( gossip_prev, 0, FD_METRICS_TOTAL_SZ );
     819             : 
     820           0 :   ulong * prev_net_tx1_bytes = aligned_alloc( 8UL, net_tile_cnt * sizeof(ulong) );
     821           0 :   ulong * prev_net_rx1_bytes = aligned_alloc( 8UL, net_tile_cnt * sizeof(ulong) );
     822           0 :   FD_TEST( prev_net_tx1_bytes );
     823           0 :   FD_TEST( prev_net_rx1_bytes );
     824           0 :   memset( prev_net_tx1_bytes, 0, net_tile_cnt * sizeof(ulong) );
     825           0 :   memset( prev_net_rx1_bytes, 0, net_tile_cnt * sizeof(ulong) );
     826             : 
     827           0 :   ulong prev_net0_rx_bytes = 0UL;
     828             : 
     829           0 :   fd_clock_t   clock_lmem[1];
     830           0 :   void       * clock_mem = aligned_alloc( FD_CLOCK_ALIGN, FD_CLOCK_FOOTPRINT );
     831           0 :   FD_TEST( clock_mem );
     832           0 :   fd_clock_default_init( clock_lmem, clock_mem );
     833             : 
     834           0 :   long start_time       = fd_clock_now( clock_lmem );
     835           0 :   long next_report_time = start_time + 1000000000L;
     836             : 
     837           0 :   for(;;) {
     838           0 :     ulong total_crds = 0UL;
     839           0 :     for( ulong i=0UL; i<FD_METRICS_ENUM_CRDS_VALUE_CNT; i++ ) total_crds += gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT )+i ];
     840           0 :     ulong total_contact_infos = gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_CONTACT_INFO_V2 ) ];
     841             : 
     842           0 :     long current_time = fd_clock_now( clock_lmem );
     843           0 :     if( FD_UNLIKELY( total_crds >= args->gossip.max_entries || total_contact_infos >= args->gossip.max_contact ) ) {
     844           0 :       long elapsed = current_time - start_time;
     845           0 :       double elapsed_secs = (double)elapsed / 1000000000.0;
     846           0 :       printf("User defined thresholds reached in %.2fs\n"
     847           0 :              "  Table Size   : %lu\n"
     848           0 :              "  Contact Infos: %lu\n",
     849           0 :              elapsed_secs, total_crds, total_contact_infos );
     850           0 :       break;
     851           0 :     }
     852             : 
     853           0 :     if( FD_LIKELY( current_time < next_report_time ) ) {
     854           0 :       continue;
     855           0 :     }
     856           0 :     next_report_time += 1000000000L;
     857             : 
     858           0 :     if( args->gossip.compact_mode ) {
     859           0 :       printf("Table Size: %lu,\tContact Infos: %lu\n",
     860           0 :              total_crds,
     861           0 :              total_contact_infos );
     862           0 :       continue;
     863           0 :     }
     864           0 : #define DIFFC(buf, METRIC) fmt_count( buf, gossip_metrics[ MIDX( COUNTER, GOSSIP, METRIC ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, METRIC ) ] )
     865           0 : #define DIFFB(buf, METRIC) fmt_bytes( buf, gossip_metrics[ MIDX( COUNTER, GOSSIP, METRIC ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, METRIC ) ] )
     866             : 
     867           0 :   char buf1[ 64 ], buf2[ 64 ], buf3[ 64 ], buf4[ 64 ], buf5[ 64 ];
     868             : 
     869           0 :   ulong total_overrun = 0UL;
     870           0 :   for( ulong i = 0UL; i < gossvf_tiles.tile_count; i++ ) {
     871           0 :     volatile ulong * net_vf_link = gossvf_tiles.net_links[i];
     872             : 
     873           0 :     ulong overrun_count = net_vf_link[ MIDX( COUNTER, LINK, OVERRUN_POLLING_FRAG_COUNT ) ] +
     874           0 :                             net_vf_link[ MIDX( COUNTER, LINK, OVERRUN_READING_FRAG_COUNT ) ];
     875             :     // printf(" Vf Tile %lu: Overrun: %s\n", i, fmt_count( buf1, overrun_count ) );
     876           0 :     total_overrun += overrun_count;
     877           0 :   }
     878           0 :   printf(" Total Overrun: %s\n", fmt_count( buf1, total_overrun ) );
     879           0 :   printf(" Total ping tracked: %lu\n", gossip_metrics[ MIDX( COUNTER, GOSSIP, PING_TRACKED_COUNT ) ] );
     880             : 
     881           0 :   for( ulong i=0UL; i<net_tile_cnt; i++ ) {
     882           0 :     if( FD_LIKELY( is_xdp ) ) {
     883           0 :       printf(" Net %lu RX bw %s, TX bw %s .. %s %s\n", i,
     884           0 :                fmt_bytes( buf1, net_metrics[ i ][ MIDX( COUNTER, NET,  RX_BYTES_TOTAL ) ] - prev_net_rx1_bytes[ i ] ),
     885           0 :                fmt_bytes( buf2, net_metrics[ i ][ MIDX( COUNTER, NET,  TX_BYTES_TOTAL ) ] - prev_net_tx1_bytes[ i ] ),
     886           0 :                fmt_count( buf3, net_metrics[ i ][ MIDX( COUNTER, NET,  RX_FILL_BLOCKED_CNT ) ] ),
     887           0 :                fmt_count( buf3, net_metrics[ i ][ MIDX( COUNTER, NET,  RX_BACKPRESSURE_CNT ) ] ) );
     888           0 :       prev_net_rx1_bytes[ i ] = net_metrics[ i ][ MIDX( COUNTER, NET,  RX_BYTES_TOTAL ) ];
     889           0 :       prev_net_tx1_bytes[ i ] = net_metrics[ i ][ MIDX( COUNTER, NET,  TX_BYTES_TOTAL ) ];
     890           0 :     } else {
     891           0 :       printf(" Net %lu RX bw %s, TX bw %s\n", i,
     892           0 :                fmt_bytes( buf1, net_metrics[ i ][ MIDX( COUNTER, SOCK, RX_BYTES_TOTAL ) ] - prev_net_rx1_bytes[ i ] ),
     893           0 :                fmt_bytes( buf2, net_metrics[ i ][ MIDX( COUNTER, SOCK, TX_BYTES_TOTAL ) ] - prev_net_tx1_bytes[ i ] ) );
     894           0 :       prev_net_rx1_bytes[ i ] = net_metrics[ i ][ MIDX( COUNTER, SOCK, RX_BYTES_TOTAL ) ];
     895           0 :       prev_net_tx1_bytes[ i ] = net_metrics[ i ][ MIDX( COUNTER, SOCK, TX_BYTES_TOTAL ) ];
     896           0 :     }
     897           0 :   }
     898             : 
     899           0 :   printf(" Single Tile RX bw %s\n", fmt_bytes( buf1, net0_link[ MIDX( COUNTER, LINK, CONSUMED_SIZE_BYTES ) ] - prev_net0_rx_bytes ) );
     900           0 :   prev_net0_rx_bytes = net0_link[ MIDX( COUNTER, LINK, CONSUMED_SIZE_BYTES ) ];
     901             : 
     902           0 :   ulong pull_response_drops = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) );
     903           0 :   ulong pull_response_success = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) );
     904           0 :   printf(" Pull response drops: %lu/%lu\n", pull_response_drops, pull_response_drops + pull_response_success);
     905             : 
     906           0 :   ulong crds_success = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_SUCCESS_PULL_RESPONSE ) );
     907           0 :   ulong crds_duplicate = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) );
     908           0 :   ulong crds_signature = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_SIGNATURE ) );
     909           0 :   ulong crds_relayer_shred = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_RELAYER_SHRED_VERSION ) );
     910           0 :   ulong crds_origin_no_contact = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_ORIGIN_NO_CONTACT_INFO ) );
     911           0 :   ulong crds_origin_shred = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_ORIGIN_SHRED_VERSION ) );
     912           0 :   ulong crds_inactive = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_INACTIVE ) );
     913             : 
     914           0 :   ulong pull_response_crds_total = crds_success + crds_duplicate + crds_signature + crds_relayer_shred + crds_origin_no_contact + crds_origin_shred + crds_inactive;
     915             : 
     916           0 :   ulong prev_crds_success = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_SUCCESS_PULL_RESPONSE ) );
     917           0 :   ulong prev_crds_duplicate = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) );
     918           0 :   ulong prev_crds_signature = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_SIGNATURE ) );
     919           0 :   ulong prev_crds_relayer_shred = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_RELAYER_SHRED_VERSION ) );
     920           0 :   ulong prev_crds_origin_no_contact = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_ORIGIN_NO_CONTACT_INFO ) );
     921           0 :   ulong prev_crds_origin_shred = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_ORIGIN_SHRED_VERSION ) );
     922           0 :   ulong prev_crds_inactive = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_INACTIVE ) );
     923             : 
     924           0 :   ulong prev_pull_response_crds_total = prev_crds_success + prev_crds_duplicate + prev_crds_signature + prev_crds_relayer_shred + prev_crds_origin_no_contact + prev_crds_origin_shred + prev_crds_inactive;
     925             : 
     926           0 :   printf(" Pull response CRDS drops: (%lu/%lu) %.1f %% (%.1f %% duplicate, %.1f %% signature, %.1f %% relayer shred version, %.1f %% origin no contact info, %.1f %% origin shred version %.1f, %% inactive)\n",
     927           0 :           pull_response_crds_total - crds_success,
     928           0 :           pull_response_crds_total,
     929           0 :           ((double)pull_response_crds_total - (double)crds_success ) / (double)pull_response_crds_total * 100.0,
     930           0 :           (double)crds_duplicate / (double)pull_response_crds_total * 100.0,
     931           0 :           (double)crds_signature / (double)pull_response_crds_total * 100.0,
     932           0 :           (double)crds_relayer_shred / (double)pull_response_crds_total * 100.0,
     933           0 :           (double)crds_origin_no_contact / (double)pull_response_crds_total * 100.0,
     934           0 :           (double)crds_origin_shred / (double)pull_response_crds_total * 100.0,
     935           0 :           (double)crds_inactive / (double)pull_response_crds_total * 100.0 );
     936             : 
     937             : 
     938           0 :   printf( " Pull response CRDS inc drops: (%lu/%lu) %1.f %% (%.1f %% duplicate, %.1f %% signature, %.1f %% relayer shred version, %.1f %% origin no contact info, %.1f %% origin shred version, %.1f %% inactive)\n\n",
     939           0 :           (pull_response_crds_total - prev_pull_response_crds_total) - (crds_success - prev_crds_success),
     940           0 :           pull_response_crds_total - prev_pull_response_crds_total,
     941           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,
     942           0 :           (double)(crds_duplicate - prev_crds_duplicate) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     943           0 :           (double)(crds_signature - prev_crds_signature) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     944           0 :           (double)(crds_relayer_shred - prev_crds_relayer_shred) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     945           0 :           (double)(crds_origin_no_contact - prev_crds_origin_no_contact) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     946           0 :           (double)(crds_origin_shred - prev_crds_origin_shred) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0,
     947           0 :           (double)(crds_inactive - prev_crds_inactive) / (double)(pull_response_crds_total - prev_pull_response_crds_total) * 100.0 );
     948             : 
     949           0 :  ulong pull_response_insertion_total = gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ] +
     950           0 :                                        gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_STALE ) ] +
     951           0 :                                        gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_WALLCLOCK ) ] +
     952           0 :                                        gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) ];
     953           0 :  ulong prev_pull_response_insertion_total = gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ] +
     954           0 :                                             gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_STALE ) ] +
     955           0 :                                             gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_WALLCLOCK ) ] +
     956           0 :                                             gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) ];
     957             : 
     958           0 :  printf(" Pull response CRDS insertion drops: (%lu/%lu) %.1f %% (%.1f %% no override, %.1f %% old, %.1f %% hash duplicate)\n",
     959           0 :          pull_response_insertion_total - gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) ],
     960           0 :          pull_response_insertion_total,
     961           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,
     962           0 :          (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_STALE ) ] / (double)pull_response_insertion_total * 100.0,
     963           0 :          (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_WALLCLOCK ) ] / (double)pull_response_insertion_total * 100.0,
     964           0 :          (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) ] / (double)pull_response_insertion_total * 100.0 );
     965           0 :  printf( " Pull response CRDS insertion inc drops: (%lu/%lu) %.1f %% (%.1f %% no override, %.1f %% old, %.1f %% hash duplicate)\n\n",
     966           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 ) ]),
     967           0 :          pull_response_insertion_total - prev_pull_response_insertion_total,
     968           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,
     969           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,
     970           0 :          (double)(gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_WALLCLOCK ) ] - gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_WALLCLOCK ) ]) / (double)(pull_response_insertion_total - prev_pull_response_insertion_total) * 100.0,
     971           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 );
     972             : 
     973             :  /* Push message statistics - similar to pull response pattern */
     974           0 :  ulong push_drops = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) );
     975           0 :  ulong push_success = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) );
     976           0 :  printf(" Push drops: %lu/%lu\n", push_drops, push_drops + push_success);
     977             : 
     978           0 :  ulong push_crds_success = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_SUCCESS_PUSH ) );
     979           0 :  ulong push_crds_signature = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_SIGNATURE ) );
     980           0 :  ulong push_crds_relayer_no_contact = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_RELAYER_NO_CONTACT_INFO ) );
     981           0 :  ulong push_crds_relayer_shred = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_RELAYER_SHRED_VERSION ) );
     982           0 :  ulong push_crds_origin_no_contact = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_ORIGIN_NO_CONTACT_INFO ) );
     983           0 :  ulong push_crds_origin_shred = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_ORIGIN_SHRED_VERSION ) );
     984           0 :  ulong push_crds_inactive = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_INACTIVE ) );
     985           0 :  ulong push_crds_wallclock = aggregate_gossvf_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_WALLCLOCK ) );
     986             : 
     987           0 :  ulong push_crds_total = push_crds_success + push_crds_signature + push_crds_relayer_no_contact + push_crds_relayer_shred + push_crds_origin_no_contact + push_crds_origin_shred + push_crds_inactive + push_crds_wallclock;
     988             : 
     989           0 :  ulong prev_push_crds_success = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_SUCCESS_PUSH ) );
     990           0 :  ulong prev_push_crds_signature = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_SIGNATURE ) );
     991           0 :  ulong prev_push_crds_relayer_no_contact = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_RELAYER_NO_CONTACT_INFO ) );
     992           0 :  ulong prev_push_crds_relayer_shred = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_RELAYER_SHRED_VERSION ) );
     993           0 :  ulong prev_push_crds_origin_no_contact = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_ORIGIN_NO_CONTACT_INFO ) );
     994           0 :  ulong prev_push_crds_origin_shred = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_ORIGIN_SHRED_VERSION ) );
     995           0 :  ulong prev_push_crds_inactive = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_INACTIVE ) );
     996           0 :  ulong prev_push_crds_wallclock = aggregate_gossvf_prev_counter( &gossvf_tiles, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_WALLCLOCK ) );
     997             : 
     998           0 :  ulong prev_push_crds_total = prev_push_crds_success + prev_push_crds_signature + prev_push_crds_relayer_no_contact + prev_push_crds_relayer_shred + prev_push_crds_origin_no_contact + prev_push_crds_origin_shred + prev_push_crds_inactive + prev_push_crds_wallclock;
     999             : 
    1000           0 :  printf(" Push CRDS drops: (%lu/%lu) %.1f %% (%.1f %% signature, %.1f %% relayer no contact info, %.1f %% relayer shred version, %.1f %% origin no contact info, %.1f %% origin shred version, %.1f %% inactive, %.1f %% wallclock)\n",
    1001           0 :          push_crds_total - push_crds_success,
    1002           0 :          push_crds_total,
    1003           0 :          ((double)push_crds_total - (double)push_crds_success ) / (double)push_crds_total * 100.0,
    1004           0 :          (double)push_crds_signature / (double)push_crds_total * 100.0,
    1005           0 :          (double)push_crds_relayer_no_contact / (double)push_crds_total * 100.0,
    1006           0 :          (double)push_crds_relayer_shred / (double)push_crds_total * 100.0,
    1007           0 :          (double)push_crds_origin_no_contact / (double)push_crds_total * 100.0,
    1008           0 :          (double)push_crds_origin_shred / (double)push_crds_total * 100.0,
    1009           0 :          (double)push_crds_inactive / (double)push_crds_total * 100.0,
    1010           0 :          (double)push_crds_wallclock / (double)push_crds_total * 100.0 );
    1011             : 
    1012             : 
    1013           0 :  printf( " Push CRDS inc drops: (%lu/%lu) %.1f %% (%.1f %% signature, %.1f %% relayer no contact info, %.1f %% relayer shred version, %.1f %% origin no contact info, %.1f %% origin shred version, %.1f %% inactive, %.1f %% wallclock)\n\n",
    1014           0 :          (push_crds_total - prev_push_crds_total) - (push_crds_success - prev_push_crds_success),
    1015           0 :          push_crds_total - prev_push_crds_total,
    1016           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,
    1017           0 :          (double)(push_crds_signature - prev_push_crds_signature) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
    1018           0 :          (double)(push_crds_relayer_no_contact - prev_push_crds_relayer_no_contact) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
    1019           0 :          (double)(push_crds_relayer_shred - prev_push_crds_relayer_shred) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
    1020           0 :          (double)(push_crds_origin_no_contact - prev_push_crds_origin_no_contact) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
    1021           0 :          (double)(push_crds_origin_shred - prev_push_crds_origin_shred) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
    1022           0 :          (double)(push_crds_inactive - prev_push_crds_inactive) / (double)(push_crds_total - prev_push_crds_total) * 100.0,
    1023           0 :          (double)(push_crds_wallclock - prev_push_crds_wallclock) / (double)(push_crds_total - prev_push_crds_total) * 100.0 );
    1024             : 
    1025           0 :  ulong push_insertion_total = gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ] +
    1026           0 :                               gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_STALE ) ] +
    1027           0 :                               gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_DUPLICATE ) ];
    1028           0 :  ulong prev_push_insertion_total = gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ] +
    1029           0 :                                    gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_STALE ) ] +
    1030           0 :                                    gossip_prev[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_DUPLICATE ) ];
    1031             : 
    1032           0 :  printf(" Push CRDS insertion drops: (%lu/%lu) %.1f %% (%.1f %% no override, %.1f %% hash duplicate)\n",
    1033           0 :          push_insertion_total - gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ],
    1034           0 :          push_insertion_total,
    1035           0 :          ((double)push_insertion_total - (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) ] ) / (double)push_insertion_total * 100.0,
    1036           0 :          (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_STALE ) ] / (double)push_insertion_total * 100.0,
    1037           0 :          (double)gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_DUPLICATE ) ] / (double)push_insertion_total * 100.0 );
    1038           0 :  printf( " Push CRDS insertion inc drops: (%lu/%lu) %.1f %% (%.1f %% no override, %.1f %% hash duplicate)\n\n",
    1039           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 ) ]),
    1040           0 :          push_insertion_total - prev_push_insertion_total,
    1041           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,
    1042           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,
    1043           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 );
    1044             : 
    1045           0 :   printf( " +------------------------+--------------+  +------------+--------------+\n" );
    1046           0 :   printf( " | CRDS Type              | Count        |  | Ping Type  | Count        |\n" );
    1047           0 :   printf( " +------------------------+--------------+  +------------+--------------+\n" );
    1048           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 ) ] ) );
    1049           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 ) ] ) );
    1050           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 ) ] ) );
    1051           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 ) ] ) );
    1052           0 :   printf( " | Snapshot Hashes        | %s |"        "  +------------+--------------+\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_SNAPSHOT_HASHES ) ] ) );
    1053           0 :   printf( " | Accounts Hashes        | %s |"        "  +------------------------+--------------+\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_ACCOUNTS_HASHES ) ] ) );
    1054           0 :   printf( " | Inc Snapshot Hashes    | %s |"        "  | Contact Info Events    | Count        |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_INCREMENTAL_SNAPSHOT_HASHES ) ] ) );
    1055           0 :   printf( " | Epoch Slots            | %s |"        "  +------------------------+--------------+\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_EPOCH_SLOTS ) ] ) );
    1056           0 :   printf( " | Version V1             | %s |"        "  | Unrecognized Socket    | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_VERSION_V1 ) ] ), fmt_count( buf2, gossip_metrics[ MIDX( COUNTER, GOSSIP, CONTACT_INFO_UNRECOGNIZED_SOCKET_TAGS ) ] ) );
    1057           0 :   printf( " | Version V2             | %s |"        "  | IPv6 Address           | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_VERSION_V2 ) ] ), fmt_count( buf2, gossip_metrics[ MIDX( COUNTER, GOSSIP, CONTACT_INFO_IPV6 ) ] ) );
    1058           0 :   printf( " | Node Instance          | %s |"        "  +------------------------+--------------+\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_NODE_INSTANCE ) ] ) );
    1059           0 :   printf( " | Duplicate Shred        | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_DUPLICATE_SHRED ) ] ) );
    1060           0 :   printf( " | Restart Last Voted     | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_RESTART_LAST_VOTED_FORK_SLOTS ) ] ) );
    1061           0 :   printf( " | Restart Heaviest       | %s |\n", fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_RESTART_HEAVIEST_FORK ) ] ) );
    1062           0 :   printf( " +------------------------+--------------+\n\n" );
    1063             : 
    1064           0 : #define DIFFX(METRIC) gossip_metrics[ MIDX( COUNTER, TILE, METRIC ) ] - gossip_prev[ MIDX( COUNTER, TILE, METRIC ) ]
    1065           0 :     ulong hkeep_ticks = DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_HOUSEKEEPING) + DIFFX(REGIME_DURATION_NANOS_PROCESSING_HOUSEKEEPING) + DIFFX(REGIME_DURATION_NANOS_BACKPRESSURE_HOUSEKEEPING);
    1066           0 :     ulong busy_ticks = DIFFX(REGIME_DURATION_NANOS_PROCESSING_PREFRAG) + DIFFX(REGIME_DURATION_NANOS_PROCESSING_POSTFRAG ) + DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_PREFRAG);
    1067           0 :     ulong caught_up_ticks = DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG);
    1068           0 :     ulong backpressure_ticks = DIFFX(REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG);
    1069           0 :     ulong total_ticks = hkeep_ticks + busy_ticks + caught_up_ticks + backpressure_ticks;
    1070             : 
    1071           0 :     printf( " Gossip Hkeep: %.1f %%  Busy: %.1f %%  Idle: %.1f %%  Backp: %0.1f %%\n",
    1072           0 :             (double)hkeep_ticks/(double)total_ticks*100.0,
    1073           0 :             (double)busy_ticks/(double)total_ticks*100.0,
    1074           0 :             (double)caught_up_ticks/(double)total_ticks*100.0,
    1075           0 :             (double)backpressure_ticks/(double)total_ticks*100.0 );
    1076           0 : #undef DIFFX
    1077             :     /* Aggregate gossvf performance metrics across all tiles */
    1078           0 :     ulong gossvf_hkeep_ticks = 0UL, gossvf_busy_ticks = 0UL, gossvf_caught_up_ticks = 0UL, gossvf_backpressure_ticks = 0UL;
    1079             : 
    1080           0 :     for( ulong i = 0UL; i < gossvf_tiles.tile_count; i++ ) {
    1081           0 :       volatile ulong * metrics = gossvf_tiles.metrics[i];
    1082           0 :       ulong * prev_metrics = gossvf_tiles.prev_metrics[i];
    1083             : 
    1084           0 : #define DIFFX(METRIC) metrics[ MIDX( COUNTER, TILE, METRIC ) ] - prev_metrics[ MIDX( COUNTER, TILE, METRIC ) ]
    1085           0 :       gossvf_hkeep_ticks += DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_HOUSEKEEPING) + DIFFX(REGIME_DURATION_NANOS_PROCESSING_HOUSEKEEPING) + DIFFX(REGIME_DURATION_NANOS_BACKPRESSURE_HOUSEKEEPING);
    1086           0 :       gossvf_busy_ticks += DIFFX(REGIME_DURATION_NANOS_PROCESSING_PREFRAG) + DIFFX(REGIME_DURATION_NANOS_PROCESSING_POSTFRAG );
    1087           0 :       gossvf_caught_up_ticks += DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_PREFRAG) + DIFFX(REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG);
    1088           0 :       gossvf_backpressure_ticks += DIFFX(REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG);
    1089           0 : #undef DIFFX
    1090           0 :     }
    1091             : 
    1092           0 :     ulong gossvf_total_ticks = gossvf_hkeep_ticks + gossvf_busy_ticks + gossvf_caught_up_ticks + gossvf_backpressure_ticks;
    1093             : 
    1094           0 :     printf( " Gossvf Hkeep: %.1f %%  Busy: %.1f %%  Idle: %.1f %%  Backp: %0.1f %% (%lu tiles)\n\n",
    1095           0 :             gossvf_total_ticks > 0UL ? (double)gossvf_hkeep_ticks/(double)gossvf_total_ticks*100.0 : 0.0,
    1096           0 :             gossvf_total_ticks > 0UL ? (double)gossvf_busy_ticks/(double)gossvf_total_ticks*100.0 : 0.0,
    1097           0 :             gossvf_total_ticks > 0UL ? (double)gossvf_caught_up_ticks/(double)gossvf_total_ticks*100.0 : 0.0,
    1098           0 :             gossvf_total_ticks > 0UL ? (double)gossvf_backpressure_ticks/(double)gossvf_total_ticks*100.0 : 0.0,
    1099           0 :             gossvf_tiles.tile_count );
    1100             : 
    1101             :     // display_gossvf_detailed( &gossvf_tiles );
    1102             : 
    1103           0 :     printf( " +--------------+--------------+--------------+--------------+--------------+--------------+\n" );
    1104           0 :     printf( " |              | Entries      | Capacity     | Utilization  | Evicted      | Expired      |\n" );
    1105           0 :     printf( " +--------------+--------------+--------------+--------------+--------------+--------------+\n" );
    1106           0 :     printf( " | Table Size   | %s | %s | %s | %s | %s |\n",
    1107           0 :       fmt_count( buf1, total_crds ),
    1108           0 :       fmt_count( buf2, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_CAPACITY ) ] ),
    1109           0 :       fmt_pct( buf3, (double)total_crds / (double)gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_CAPACITY ) ] ),
    1110           0 :       fmt_count( buf4, gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_EVICTED_COUNT ) ] ),
    1111           0 :       fmt_count( buf5, gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_EXPIRED_COUNT ) ] ) );
    1112           0 :     printf( " | Contact Info | %s | %s | %s | %s |          n/a |\n",
    1113           0 :       fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_CONTACT_INFO_V2 ) ] ),
    1114           0 :       fmt_count( buf2, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PEER_CAPACITY ) ] ),
    1115           0 :       fmt_pct( buf3, (double)gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_COUNT_CONTACT_INFO_V2 ) ] / (double)gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PEER_CAPACITY ) ] ),
    1116           0 :       fmt_count( buf4, gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_PEER_EVICTED_COUNT ) ] ) );
    1117           0 :     printf( " | Purged       | %s | %s | %s | %s | %s |\n",
    1118           0 :       fmt_count( buf1, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PURGED_COUNT ) ] ),
    1119           0 :       fmt_count( buf2, gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PURGED_CAPACITY ) ] ),
    1120           0 :       fmt_pct( buf3, (double)gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PURGED_COUNT ) ] / (double)gossip_metrics[ MIDX( GAUGE, GOSSIP, CRDS_PURGED_CAPACITY ) ] ),
    1121           0 :       fmt_count( buf4, gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_PURGED_EVICTED_COUNT ) ] ),
    1122           0 :       fmt_count( buf5, gossip_metrics[ MIDX( COUNTER, GOSSIP, CRDS_PURGED_EXPIRED_COUNT ) ] ) );
    1123           0 :     printf( " +--------------+--------------+--------------+--------------+--------------+--------------+\n\n" );
    1124             : 
    1125           0 :     rx_deltas_t deltas = rx_deltas_aggregated( gossip_metrics, gossip_prev, &gossvf_tiles );
    1126             : 
    1127           0 :     printf( " +--------------------------------------------------------------------------+--------------+\n" );
    1128           0 :     printf( " |              | RX count     | RX drops     | TX count     | RX bits      | TX bits      |\n" );
    1129           0 :     printf( " +--------------+--------------+--------------+--------------+--------------+--------------+\n" );
    1130           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 ) );
    1131           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 ) );
    1132           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 ) );
    1133           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 ) );
    1134           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 ) );
    1135           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 ) );
    1136           0 :     printf( " +--------------+--------------+--------------+--------------+--------------+--------------+\n\n" );
    1137             : 
    1138             :     // printf( " +--------------------------------------------------------------------------+\n" );
    1139             :     // printf( " |              | RX count     | TX count     | RX bytes     | TX bytes     |\n" );
    1140             :     // printf( " +--------------+--------------+--------------+--------------+--------------+\n" );
    1141             :     // printf( " | Pull Request | %s | %s | %s | %s |\n", DIFFC( buf1, MESSAGE_RX_COUNT_PULL_REQUEST ), DIFFC( buf2, MESSAGE_TX_COUNT_PULL_REQUEST ), DIFFB( buf3, MESSAGE_RX_BYTES_PULL_REQUEST ), DIFFB( buf4, MESSAGE_TX_BYTES_PULL_REQUEST ) );
    1142             :     // printf( " | Pull Response| %s | %s | %s | %s |\n", DIFFC( buf1, MESSAGE_RX_COUNT_PULL_RESPONSE ), DIFFC( buf2, MESSAGE_TX_COUNT_PULL_RESPONSE ), DIFFB( buf3, MESSAGE_RX_BYTES_PULL_RESPONSE ), DIFFB( buf4, MESSAGE_TX_BYTES_PULL_RESPONSE ) );
    1143             :     // printf( " | Push         | %s | %s | %s | %s |\n", DIFFC( buf1, MESSAGE_RX_COUNT_PUSH ), DIFFC( buf2, MESSAGE_TX_COUNT_PUSH ), DIFFB( buf3, MESSAGE_RX_BYTES_PUSH ), DIFFB( buf4, MESSAGE_TX_BYTES_PUSH ) );
    1144             :     // printf( " | Prune        | %s | %s | %s | %s |\n", DIFFC( buf1, MESSAGE_RX_COUNT_PRUNE ), DIFFC( buf2, MESSAGE_TX_COUNT_PRUNE ), DIFFB( buf3, MESSAGE_RX_BYTES_PRUNE ), DIFFB( buf4, MESSAGE_TX_BYTES_PRUNE ) );
    1145             :     // printf( " | Ping         | %s | %s | %s | %s |\n", DIFFC( buf1, MESSAGE_RX_COUNT_PING ), DIFFC( buf2, MESSAGE_TX_COUNT_PING ), DIFFB( buf3, MESSAGE_RX_BYTES_PING ), DIFFB( buf4, MESSAGE_TX_BYTES_PING ) );
    1146             :     // printf( " | Pong         | %s | %s | %s | %s |\n", DIFFC( buf1, MESSAGE_RX_COUNT_PONG ), DIFFC( buf2, MESSAGE_TX_COUNT_PONG ), DIFFB( buf3, MESSAGE_RX_BYTES_PONG ), DIFFB( buf4, MESSAGE_TX_BYTES_PONG ) );
    1147             :     // printf( " +--------------------------------------------------------------------------+\n\n" );
    1148             : 
    1149           0 :     for( ulong i=0UL; i<FD_METRICS_TOTAL_SZ/sizeof(ulong); i++ ) gossip_prev[ i ] = gossip_metrics[ i ];
    1150             : 
    1151             :     /* Update previous metrics for all gossvf tiles */
    1152           0 :     for( ulong tile_idx = 0UL; tile_idx < gossvf_tiles.tile_count; tile_idx++ ) {
    1153           0 :       for( ulong i=0UL; i<FD_METRICS_TOTAL_SZ/sizeof(ulong); i++ ) {
    1154           0 :         gossvf_tiles.prev_metrics[tile_idx][ i ] = gossvf_tiles.metrics[tile_idx][ i ];
    1155           0 :       }
    1156           0 :     }
    1157           0 :   }
    1158           0 : }
    1159             : 
    1160             : action_t fd_action_gossip = {
    1161             :   .name = "gossip",
    1162             :   .args = gossip_args,
    1163             :   .fn   = gossip_cmd_fn,
    1164             :   .perm = gossip_cmd_perm,
    1165             :   .topo = gossip_cmd_topo,
    1166             : };

Generated by: LCOV version 1.14