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

Generated by: LCOV version 1.14