LCOV - code coverage report
Current view: top level - app/firedancer-dev/commands - gossip.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 188 0.0 %
Date: 2026-03-19 18:19:27 Functions: 0 6 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_topob.h"
       5             : #include "../../../disco/net/fd_net_tile.h" /* fd_topos_net_tiles */
       6             : #include "../../../disco/metrics/fd_metrics.h"
       7             : #include "../../../discof/gossip/fd_gossip_tile.h"
       8             : #include "../../../util/clock/fd_clock.h"
       9             : 
      10             : #include "../../firedancer/commands/monitor_gossip/gossip_diag.h"
      11             : 
      12             : #include "core_subtopo.h"
      13             : #include "gossip.h"
      14             : 
      15             : #include <stdio.h> /* printf */
      16             : #include <stdlib.h>
      17             : #include <unistd.h> /* isatty */
      18             : #include <sys/ioctl.h>
      19             : 
      20             : extern fd_topo_obj_callbacks_t * CALLBACKS[];
      21             : 
      22             : fd_topo_run_tile_t
      23             : fdctl_tile_run( fd_topo_tile_t const * tile );
      24             : 
      25             : void
      26             : resolve_gossip_entrypoints( config_t * config );
      27             : 
      28             : static void
      29           0 : gossip_cmd_topo( config_t * config ) {
      30           0 :   resolve_gossip_entrypoints( config );
      31             : 
      32             :   /* Disable non-gossip listen ports */
      33           0 :   config->tiles.shred.shred_listen_port = 0U;
      34           0 :   config->tiles.quic.quic_transaction_listen_port = 0U;
      35           0 :   config->tiles.quic.regular_transaction_listen_port = 0U;
      36           0 :   config->tiles.repair.repair_intake_listen_port = 0U;
      37           0 :   config->tiles.repair.repair_serve_listen_port = 0U;
      38           0 :   config->tiles.txsend.txsend_src_port = 0U;
      39             : 
      40           0 :   static ulong tile_to_cpu[ FD_TILE_MAX ] = {0}; /* TODO */
      41             : 
      42           0 :   ulong net_tile_cnt = config->layout.net_tile_count;
      43             : 
      44             :   /* Reset topology from scratch */
      45           0 :   fd_topo_t * topo = &config->topo;
      46           0 :   fd_topob_new( &config->topo, config->name );
      47           0 :   topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
      48             : 
      49           0 :   fd_core_subtopo(   config, tile_to_cpu );
      50           0 :   fd_gossip_subtopo( config, tile_to_cpu );
      51             : 
      52           0 :   fd_topob_tile_in( topo, "gossip", 0UL, "metric_in", "sign_gossip",  0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
      53           0 :   for( ulong i=0UL; i<net_tile_cnt; i++ ) fd_topos_net_tile_finish( topo, i );
      54           0 :   fd_topob_auto_layout( topo, 0 );
      55           0 :   fd_topob_finish( topo, CALLBACKS );
      56           0 : }
      57             : 
      58             : void
      59           0 : fd_gossip_subtopo( config_t * config, ulong tile_to_cpu[ FD_TILE_MAX ] FD_PARAM_UNUSED ) {
      60           0 :   fd_topo_t * topo = &config->topo;
      61             : 
      62           0 :   ulong gossvf_tile_count = config->firedancer.layout.gossvf_tile_count;
      63           0 :   ulong net_tile_cnt = config->layout.net_tile_count;
      64             : 
      65           0 :   static char* const tiles_to_add[] = {
      66           0 :     "gossvf",
      67           0 :     "ipecho",
      68           0 :     "gossip",
      69           0 :   };
      70           0 :   for( int i=0; i<3; ++i) FD_TEST( fd_topo_find_tile( topo, tiles_to_add[i], 0UL ) == ULONG_MAX );
      71             : 
      72           0 :   fd_topob_wksp( topo, "gossip" );
      73           0 :   fd_topo_tile_t * gossip_tile = fd_topob_tile( topo, "gossip", "gossip", "metric_in", 0UL, 0, 1, 0 );
      74           0 :   fd_cstr_ncpy( gossip_tile->gossip.identity_key_path, config->paths.identity_key, sizeof(gossip_tile->gossip.identity_key_path) );
      75           0 :   gossip_tile->gossip.entrypoints_cnt        = config->gossip.entrypoints_cnt;
      76           0 :   for( ulong i=0UL; i<config->gossip.entrypoints_cnt; i++ ) {
      77           0 :     gossip_tile->gossip.entrypoints[ i ] = config->gossip.resolved_entrypoints[ i ];
      78           0 :   }
      79           0 :   gossip_tile->gossip.ip_addr              = config->net.ip_addr;
      80           0 :   gossip_tile->gossip.shred_version        = config->consensus.expected_shred_version;
      81           0 :   gossip_tile->gossip.max_entries          = config->tiles.gossip.max_entries;
      82           0 :   gossip_tile->gossip.ports.gossip         = config->gossip.port;
      83           0 :   gossip_tile->gossip.ports.repair         = 0;
      84           0 :   gossip_tile->gossip.ports.tpu            = 0;
      85           0 :   gossip_tile->gossip.ports.tpu_quic       = 0;
      86           0 :   gossip_tile->gossip.ports.tvu            = 0;
      87           0 :   gossip_tile->gossip.ports.tvu_quic       = 0;
      88           0 :   gossip_tile->gossip.boot_timestamp_nanos = config->boot_timestamp_nanos;
      89             : 
      90           0 :   fd_topob_wksp( topo, "gossvf" );
      91           0 :   for( ulong i=0UL; i<gossvf_tile_count; i++ ) {
      92           0 :     fd_topo_tile_t * gossvf_tile = fd_topob_tile( topo, "gossvf", "gossvf", "metric_in", 0UL, 0, 1, 0 );
      93           0 :     fd_cstr_ncpy( gossvf_tile->gossvf.identity_key_path, config->paths.identity_key, sizeof(gossvf_tile->gossvf.identity_key_path) );
      94           0 :     gossvf_tile->gossvf.tcache_depth = 1UL<<22UL;
      95           0 :     gossvf_tile->gossvf.shred_version = config->consensus.expected_shred_version;
      96           0 :     gossvf_tile->gossvf.allow_private_address = config->development.gossip.allow_private_address;
      97           0 :     gossvf_tile->gossvf.entrypoints_cnt = config->gossip.entrypoints_cnt;
      98           0 :     gossvf_tile->gossvf.boot_timestamp_nanos = config->boot_timestamp_nanos;
      99           0 :     for( ulong i=0UL; i<config->gossip.entrypoints_cnt; i++ ) {
     100           0 :       gossvf_tile->gossvf.entrypoints[ i ] = config->gossip.resolved_entrypoints[ i ];
     101           0 :     }
     102           0 :   }
     103           0 :   for( ulong i=0UL; i<net_tile_cnt; i++ ) {
     104           0 :     fd_topos_net_rx_link( topo, "net_gossvf", i, config->net.ingress_buffer_size );
     105           0 :   }
     106           0 :   for( ulong i=0UL; i<gossvf_tile_count; i++ ) {
     107           0 :     for( ulong j=0UL; j<net_tile_cnt; j++ ) {
     108           0 :       fd_topob_tile_in( topo, "gossvf", i, "metric_in", "net_gossvf", j, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     109           0 :     }
     110           0 :   }
     111             : 
     112           0 :   fd_topob_wksp( topo, "gossip_net" );
     113           0 :   fd_topob_link( topo, "gossip_net", "gossip_net", 65536*4UL, FD_NET_MTU, 1UL );
     114           0 :   fd_topos_tile_in_net( topo, "metric_in", "gossip_net", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     115           0 :   fd_topob_tile_out( topo, "gossip", 0UL, "gossip_net", 0UL );
     116             : 
     117           0 :   fd_topob_wksp( topo, "ipecho" );
     118           0 :   fd_topo_tile_t * ipecho_tile = fd_topob_tile( topo, "ipecho", "ipecho", "metric_in", 0UL, 0, 0, 0 );
     119           0 :   ipecho_tile->ipecho.expected_shred_version = config->consensus.expected_shred_version;
     120           0 :   ipecho_tile->ipecho.bind_address = config->net.ip_addr;
     121           0 :   ipecho_tile->ipecho.bind_port = config->gossip.port;
     122           0 :   ipecho_tile->ipecho.entrypoints_cnt = config->gossip.entrypoints_cnt;
     123           0 :   for( ulong i=0UL; i<config->gossip.entrypoints_cnt; i++ ) {
     124           0 :     ipecho_tile->ipecho.entrypoints[ i ] = config->gossip.resolved_entrypoints[ i ];
     125           0 :   }
     126             : 
     127           0 :   fd_topob_wksp( topo, "ipecho_out" );
     128           0 :   fd_topob_link( topo, "ipecho_out", "ipecho_out", 4UL, 0UL, 1UL );
     129           0 :   fd_topob_tile_out( topo, "ipecho", 0UL, "ipecho_out", 0UL );
     130             : 
     131           0 :   for( ulong i=0UL; i<gossvf_tile_count; i++ ) {
     132           0 :     fd_topob_tile_in( topo, "gossvf", i, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     133           0 :   }
     134           0 :   fd_topob_tile_in( topo, "gossip", 0UL, "metric_in", "ipecho_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     135             : 
     136           0 :   fd_topob_wksp( topo, "gossvf_gossip" );
     137           0 :   fd_topob_wksp( topo, "gossip_gossvf" );
     138           0 :   fd_topob_wksp( topo, "gossip_out" );
     139             : 
     140           0 :   fd_topob_link(     topo, "gossip_gossvf", "gossip_gossvf", 65536UL*4, sizeof(fd_gossip_ping_update_t), 1UL );
     141           0 :   fd_topob_tile_out( topo, "gossip", 0UL, "gossip_gossvf", 0UL );
     142             : 
     143           0 :   fd_topob_link( topo, "gossip_out", "gossip_out", 65536UL*4, sizeof(fd_gossip_update_message_t), 1UL );
     144           0 :   fd_topob_tile_out( topo, "gossip", 0UL, "gossip_out", 0UL );
     145           0 :   for( ulong i=0UL; i<gossvf_tile_count; i++ ) {
     146           0 :     fd_topob_link(     topo, "gossvf_gossip", "gossvf_gossip", 65536UL*4, sizeof(fd_gossip_message_t)+FD_GOSSIP_MESSAGE_MAX_CRDS+FD_NET_MTU, 1UL );
     147           0 :     fd_topob_tile_out( topo, "gossvf", i, "gossvf_gossip", i );
     148           0 :     fd_topob_tile_in(  topo, "gossip", 0UL, "metric_in", "gossvf_gossip", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     149             : 
     150             :     /* Only one link_kind for gossip_out broadcast link */
     151           0 :     fd_topob_tile_in( topo, "gossvf", i, "metric_in", "gossip_gossvf", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     152           0 :     fd_topob_tile_in( topo, "gossvf", i, "metric_in", "gossip_out",    0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     153           0 :   }
     154             : 
     155           0 :   fd_topob_wksp( topo, "gossip_sign"  );
     156           0 :   fd_topob_link( topo, "gossip_sign", "gossip_sign", 128UL, 2048UL, 1UL );
     157           0 :   fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "gossip_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     158           0 :   fd_topob_wksp( topo, "sign_gossip"  );
     159           0 :   fd_topob_link( topo, "sign_gossip", "sign_gossip", 128UL, 64UL, 1UL );
     160           0 :   fd_topob_tile_out( topo, "sign", 0UL, "sign_gossip", 0UL );
     161           0 :   fd_topob_tile_out( topo, "gossip", 0UL, "gossip_sign", 0UL );
     162           0 : }
     163             : 
     164             : static args_t
     165           0 : configure_args( void ) {
     166           0 :   args_t args = {
     167           0 :     .configure.command = CONFIGURE_CMD_INIT,
     168           0 :   };
     169             : 
     170           0 :   ulong stage_idx = 0UL;
     171           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_hugetlbfs;
     172           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_sysctl;
     173           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_bonding;
     174           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_ethtool_channels;
     175           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_ethtool_offloads;
     176           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_ethtool_loopback;
     177           0 :   args.configure.stages[ stage_idx++ ] = NULL;
     178             : 
     179           0 :   return args;
     180           0 : }
     181             : 
     182             : void
     183             : gossip_cmd_perm( args_t *         args FD_PARAM_UNUSED,
     184             :                  fd_cap_chk_t *   chk,
     185           0 :                  config_t const * config ) {
     186           0 :   args_t c_args = configure_args();
     187           0 :   configure_cmd_perm( &c_args, chk, config );
     188           0 :   run_cmd_perm( NULL, chk, config );
     189           0 : }
     190             : 
     191             : /* Display helper functions and types have been extracted to
     192             :    gossip_diag.h / gossip_diag.c in the shared commands directory. */
     193             : 
     194             : static void
     195             : gossip_args( int *    pargc,
     196             :              char *** pargv,
     197           0 :              args_t * args  ) {
     198           0 :   if( FD_UNLIKELY( fd_env_strip_cmdline_contains( pargc, pargv, "--help" ) ) ) {
     199           0 :     fputs(
     200           0 :       "\nUsage: firedancer-dev gossip [GLOBAL FLAGS] [FLAGS]\n"
     201           0 :       "\n"
     202           0 :       "Global Flags:\n"
     203           0 :       "  --mainnet            Use Solana mainnet-beta defaults\n"
     204           0 :       "  --testnet            Use Solana testnet defaults\n"
     205           0 :       "  --devnet             Use Solana devnet defaults\n"
     206           0 :       "\n"
     207           0 :       "Flags:\n"
     208           0 :       "  --max-entries <num>         Exit once we see <num> CRDS entries in table\n"
     209           0 :       "  --max-contact-infos <num>   Exit once we see <num> contact infos in table\n"
     210           0 :       "  --compact                   Use compact output format\n"
     211           0 :       "\n",
     212           0 :       stderr );
     213           0 :     exit( EXIT_SUCCESS );
     214           0 :   }
     215             : 
     216           0 :   args->gossip.max_entries  = fd_env_strip_cmdline_ulong   ( pargc, pargv, "--max-entries", NULL, ULONG_MAX );
     217           0 :   args->gossip.max_contact  = fd_env_strip_cmdline_ulong   ( pargc, pargv, "--max-contact-infos", NULL, ULONG_MAX );
     218           0 :   args->gossip.compact_mode = fd_env_strip_cmdline_contains( pargc, pargv, "--compact" );
     219           0 : }
     220             : 
     221             : void
     222             : gossip_cmd_fn( args_t *   args,
     223           0 :                config_t * config ) {
     224           0 :   args_t c_args = configure_args();
     225           0 :   configure_cmd_fn( &c_args, config );
     226             : 
     227           0 :   run_firedancer_init( config, 1, 1 );
     228             : 
     229           0 :   int const is_xdp = ( 0==strcmp( config->net.provider, "xdp" ) );
     230           0 :   if( is_xdp ) fd_topo_install_xdp_simple( &config->topo, config->net.bind_address_parsed );
     231           0 :   fd_topo_join_workspaces( &config->topo, FD_SHMEM_JOIN_MODE_READ_WRITE, FD_TOPO_CORE_DUMP_LEVEL_DISABLED );
     232           0 :   fd_topo_fill( &config->topo );
     233             : 
     234             :   /* FIXME allow running sandboxed/multiprocess */
     235           0 :   fd_topo_run_single_process( &config->topo, 2, config->uid, config->gid, fdctl_tile_run );
     236             : 
     237           0 :   fd_gossip_diag_ctx_t diag_ctx[1];
     238           0 :   if( FD_UNLIKELY( fd_gossip_diag_init( diag_ctx, &config->topo, config ) ) )
     239           0 :     FD_LOG_ERR(( "Failed to initialize gossip diagnostics" ));
     240             : 
     241           0 :   fd_clock_t   clock_lmem[1];
     242           0 :   void       * clock_mem = aligned_alloc( FD_CLOCK_ALIGN, FD_CLOCK_FOOTPRINT );
     243           0 :   FD_TEST( clock_mem );
     244           0 :   fd_clock_default_init( clock_lmem, clock_mem );
     245             : 
     246           0 :   long start_time       = fd_clock_now( clock_lmem );
     247           0 :   long next_report_time = start_time + 1000000000L;
     248             : 
     249           0 :   for(;;) {
     250           0 :     long current_time = fd_clock_now( clock_lmem );
     251             : 
     252           0 :     if( FD_LIKELY( current_time < next_report_time ) ) {
     253           0 :       continue;
     254           0 :     }
     255           0 :     next_report_time += 1000000000L;
     256             : 
     257           0 :     fd_gossip_diag_render( diag_ctx, args->gossip.compact_mode );
     258             : 
     259           0 :     if( FD_UNLIKELY( diag_ctx->last_total_crds >= args->gossip.max_entries ||
     260           0 :                      diag_ctx->last_total_contact_infos >= args->gossip.max_contact ) ) {
     261           0 :       long elapsed = current_time - start_time;
     262           0 :       double elapsed_secs = (double)elapsed / 1000000000.0;
     263           0 :       printf( "User defined thresholds reached in %.2fs\n"
     264           0 :               "  Table Size   : %lu\n"
     265           0 :               "  Contact Infos: %lu\n",
     266           0 :               elapsed_secs, diag_ctx->last_total_crds, diag_ctx->last_total_contact_infos );
     267           0 :       break;
     268           0 :     }
     269           0 :   }
     270           0 : }
     271             : 
     272             : action_t fd_action_gossip = {
     273             :   .name = "gossip",
     274             :   .args = gossip_args,
     275             :   .fn   = gossip_cmd_fn,
     276             :   .perm = gossip_cmd_perm,
     277             :   .topo = gossip_cmd_topo,
     278             : };

Generated by: LCOV version 1.14