LCOV - code coverage report
Current view: top level - app/fdctl/run/topos - fd_frankendancer.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 220 330 66.7 %
Date: 2024-11-13 11:58:15 Functions: 1 1 100.0 %

          Line data    Source code
       1             : #include "../../fdctl.h"
       2             : 
       3             : #include "../../../../disco/tiles.h"
       4             : #include "../../../../disco/topo/fd_topob.h"
       5             : #include "../../../../disco/topo/fd_pod_format.h"
       6             : #include "../../../../util/tile/fd_tile_private.h"
       7             : #include "../../../../util/shmem/fd_shmem_private.h"
       8             : 
       9             : void
      10           3 : fd_topo_initialize( config_t * config ) {
      11           3 :   ulong net_tile_cnt    = config->layout.net_tile_count;
      12           3 :   ulong quic_tile_cnt   = config->layout.quic_tile_count;
      13           3 :   ulong verify_tile_cnt = config->layout.verify_tile_count;
      14           3 :   ulong resolv_tile_cnt = config->layout.resolv_tile_count;
      15           3 :   ulong bank_tile_cnt   = config->layout.bank_tile_count;
      16           3 :   ulong shred_tile_cnt  = config->layout.shred_tile_count;
      17             : 
      18           3 :   fd_topo_t * topo = { fd_topob_new( &config->topo, config->name ) };
      19             : 
      20             :   /*             topo, name */
      21           3 :   fd_topob_wksp( topo, "net_quic"     );
      22           3 :   fd_topob_wksp( topo, "net_shred"    );
      23           3 :   fd_topob_wksp( topo, "quic_verify"  );
      24           3 :   fd_topob_wksp( topo, "verify_dedup" );
      25           3 :   fd_topob_wksp( topo, "dedup_resolv" );
      26           3 :   fd_topob_wksp( topo, "resolv_pack"  );
      27           3 :   fd_topob_wksp( topo, "pack_bank"    );
      28           3 :   fd_topob_wksp( topo, "bank_poh"     );
      29           3 :   fd_topob_wksp( topo, "bank_busy"    );
      30           3 :   fd_topob_wksp( topo, "poh_shred"    );
      31           3 :   fd_topob_wksp( topo, "gossip_dedup" );
      32           3 :   fd_topob_wksp( topo, "shred_store"  );
      33           3 :   fd_topob_wksp( topo, "stake_out"    );
      34           3 :   fd_topob_wksp( topo, "metric_in"    );
      35             : 
      36           3 :   fd_topob_wksp( topo, "shred_sign"   );
      37           3 :   fd_topob_wksp( topo, "sign_shred"   );
      38             : 
      39           3 :   fd_topob_wksp( topo, "net"          );
      40           3 :   fd_topob_wksp( topo, "quic"         );
      41           3 :   fd_topob_wksp( topo, "verify"       );
      42           3 :   fd_topob_wksp( topo, "dedup"        );
      43           3 :   fd_topob_wksp( topo, "resolv"       );
      44           3 :   fd_topob_wksp( topo, "pack"         );
      45           3 :   fd_topob_wksp( topo, "bank"         );
      46           3 :   fd_topob_wksp( topo, "poh"          );
      47           3 :   fd_topob_wksp( topo, "shred"        );
      48           3 :   fd_topob_wksp( topo, "store"        );
      49           3 :   fd_topob_wksp( topo, "sign"         );
      50           3 :   fd_topob_wksp( topo, "metric"       );
      51           3 :   fd_topob_wksp( topo, "cswtch"       );
      52             : 
      53         309 :   #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
      54             : 
      55             :   /*                                  topo, link_name,      wksp_name,      is_reasm, depth,                                    mtu,                    burst */
      56           3 :   FOR(net_tile_cnt)    fd_topob_link( topo, "net_quic",     "net_quic",     0,        config->tiles.net.send_buffer_size,       FD_NET_MTU,             1UL );
      57           3 :   FOR(net_tile_cnt)    fd_topob_link( topo, "net_shred",    "net_shred",    0,        config->tiles.net.send_buffer_size,       FD_NET_MTU,             1UL );
      58           3 :   FOR(quic_tile_cnt)   fd_topob_link( topo, "quic_net",     "net_quic",     0,        config->tiles.net.send_buffer_size,       FD_NET_MTU,             1UL );
      59           3 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_net",    "net_shred",    0,        config->tiles.net.send_buffer_size,       FD_NET_MTU,             1UL );
      60           3 :   FOR(quic_tile_cnt)   fd_topob_link( topo, "quic_verify",  "quic_verify",  1,        config->tiles.verify.receive_buffer_size, 0UL,                    config->tiles.quic.txn_reassembly_count );
      61          12 :   FOR(verify_tile_cnt) fd_topob_link( topo, "verify_dedup", "verify_dedup", 0,        config->tiles.verify.receive_buffer_size, FD_TPU_DCACHE_MTU,      1UL );
      62             :   /* gossip_dedup could be FD_TPU_MTU, since txns are not parsed, but better to just share one size for all the ins of dedup */
      63           3 :   /**/                 fd_topob_link( topo, "gossip_dedup", "gossip_dedup", 0,        2048UL,                                   FD_TPU_DCACHE_MTU,      1UL );
      64             :   /* dedup_pack is large currently because pack can encounter stalls when running at very high throughput rates that would
      65             :      otherwise cause drops. */
      66           3 :   /**/                 fd_topob_link( topo, "dedup_resolv", "dedup_resolv", 0,        65536UL,                                  FD_TPU_DCACHE_MTU,      1UL );
      67           3 :   FOR(resolv_tile_cnt) fd_topob_link( topo, "resolv_pack",  "resolv_pack",  0,        65536UL,                                  FD_TPU_RESOLVED_DCACHE_MTU, 1UL );
      68           3 :   /**/                 fd_topob_link( topo, "stake_out",    "stake_out",    0,        128UL,                                    40UL + 40200UL * 40UL,  1UL );
      69             :   /* pack_bank is shared across all banks, so if one bank stalls due to complex transactions, the buffer neeeds to be large so that
      70             :      other banks can keep proceeding. */
      71           3 :   /**/                 fd_topob_link( topo, "pack_bank",    "pack_bank",    0,        65536UL,                                  USHORT_MAX,             1UL );
      72           6 :   FOR(bank_tile_cnt)   fd_topob_link( topo, "bank_poh",     "bank_poh",     0,        128UL,                                    USHORT_MAX,             1UL );
      73           3 :   /**/                 fd_topob_link( topo, "poh_pack",     "bank_poh",     0,        128UL,                                    sizeof(fd_became_leader_t), 1UL );
      74           3 :   /**/                 fd_topob_link( topo, "poh_shred",    "poh_shred",    0,        16384UL,                                  USHORT_MAX,             1UL );
      75           3 :   /**/                 fd_topob_link( topo, "crds_shred",   "poh_shred",    0,        128UL,                                    8UL  + 40200UL * 38UL,  1UL );
      76           3 :   /**/                 fd_topob_link( topo, "replay_resol", "bank_poh",     0,        128UL,                                    sizeof(fd_completed_bank_t), 1UL );
      77             :   /* See long comment in fd_shred.c for an explanation about the size of this dcache. */
      78           3 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_store",  "shred_store",  0,        16384UL,                                  4UL*FD_SHRED_STORE_MTU, 4UL+config->tiles.shred.max_pending_shred_sets );
      79             : 
      80           3 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "shred_sign",   "shred_sign",   0,        128UL,                                    32UL,                   1UL );
      81           3 :   FOR(shred_tile_cnt)  fd_topob_link( topo, "sign_shred",   "sign_shred",   0,        128UL,                                    64UL,                   1UL );
      82             : 
      83           3 :   ushort parsed_tile_to_cpu[ FD_TILE_MAX ];
      84             :   /* Unassigned tiles will be floating, unless auto topology is enabled. */
      85        3075 :   for( ulong i=0UL; i<FD_TILE_MAX; i++ ) parsed_tile_to_cpu[ i ] = USHORT_MAX;
      86             : 
      87           3 :   int is_auto_affinity = !strcmp( config->layout.affinity, "auto" );
      88           3 :   int is_agave_auto_affinity = !strcmp( config->layout.agave_affinity, "auto" );
      89           3 :   int is_bench_auto_affinity = !strcmp( config->development.bench.affinity, "auto" );
      90             : 
      91           3 :   if( FD_UNLIKELY( is_auto_affinity != is_agave_auto_affinity ||
      92           3 :                    is_auto_affinity != is_bench_auto_affinity ) ) {
      93           0 :     FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.affinity], [layout.agave_affinity], and [development.bench.affinity] must all be set to 'auto' or all be set to a specific CPU affinity string." ));
      94           0 :   }
      95             : 
      96           3 :   ulong affinity_tile_cnt = 0UL;
      97           3 :   if( FD_LIKELY( !is_auto_affinity ) ) affinity_tile_cnt = fd_tile_private_cpus_parse( config->layout.affinity, parsed_tile_to_cpu );
      98             : 
      99           3 :   ulong tile_to_cpu[ FD_TILE_MAX ] = {0};
     100           3 :   for( ulong i=0UL; i<affinity_tile_cnt; i++ ) {
     101           0 :     if( FD_UNLIKELY( parsed_tile_to_cpu[ i ]!=USHORT_MAX && parsed_tile_to_cpu[ i ]>=fd_numa_cpu_cnt() ) )
     102           0 :       FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.affinity] specifies a CPU index of %hu, but the system "
     103           0 :                    "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
     104           0 :                    "in the system.",
     105           0 :                    parsed_tile_to_cpu[ i ], fd_numa_cpu_cnt() ));
     106           0 :     tile_to_cpu[ i ] = fd_ulong_if( parsed_tile_to_cpu[ i ]==USHORT_MAX, ULONG_MAX, (ulong)parsed_tile_to_cpu[ i ] );
     107           0 :   }
     108             : 
     109             :   /*                                  topo, tile_name, tile_wksp, metrics_wksp, cpu_idx,                       is_agave */
     110           3 :   FOR(net_tile_cnt)    fd_topob_tile( topo, "net",     "net",     "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     111           3 :   FOR(quic_tile_cnt)   fd_topob_tile( topo, "quic",    "quic",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     112          12 :   FOR(verify_tile_cnt) fd_topob_tile( topo, "verify",  "verify",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     113           3 :   /**/                 fd_topob_tile( topo, "dedup",   "dedup",   "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     114           3 :   FOR(resolv_tile_cnt) fd_topob_tile( topo, "resolv",  "resolv",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 1 );
     115           3 :   /**/                 fd_topob_tile( topo, "pack",    "pack",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     116           6 :   FOR(bank_tile_cnt)   fd_topob_tile( topo, "bank",    "bank",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 1 );
     117           3 :   /**/                 fd_topob_tile( topo, "poh",     "poh",     "metric_in",  tile_to_cpu[ topo->tile_cnt ], 1 );
     118           3 :   FOR(shred_tile_cnt)  fd_topob_tile( topo, "shred",   "shred",   "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     119           3 :   /**/                 fd_topob_tile( topo, "store",   "store",   "metric_in",  tile_to_cpu[ topo->tile_cnt ], 1 );
     120           3 :   /**/                 fd_topob_tile( topo, "sign",    "sign",    "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     121           3 :   /**/                 fd_topob_tile( topo, "metric",  "metric",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     122           3 :   /**/                 fd_topob_tile( topo, "cswtch",  "cswtch",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     123             : 
     124           3 :   if( FD_LIKELY( !is_auto_affinity ) ) {
     125           0 :     if( FD_UNLIKELY( affinity_tile_cnt<topo->tile_cnt ) )
     126           0 :       FD_LOG_ERR(( "The topology you are using has %lu tiles, but the CPU affinity specified in the config tile as [layout.affinity] only provides for %lu cores. "
     127           0 :                    "You should either increase the number of cores dedicated to Firedancer in the affinity string, or decrease the number of cores needed by reducing "
     128           0 :                    "the total tile count. You can reduce the tile count by decreasing individual tile counts in the [layout] section of the configuration file.",
     129           0 :                    topo->tile_cnt, affinity_tile_cnt ));
     130           0 :     if( FD_UNLIKELY( affinity_tile_cnt>topo->tile_cnt ) )
     131           0 :       FD_LOG_WARNING(( "The topology you are using has %lu tiles, but the CPU affinity specified in the config tile as [layout.affinity] provides for %lu cores. "
     132           0 :                        "Not all cores in the affinity will be used by Firedancer. You may wish to increase the number of tiles in the system by increasing "
     133           0 :                        "individual tile counts in the [layout] section of the configuration file.",
     134           0 :                        topo->tile_cnt, affinity_tile_cnt ));
     135             : 
     136           0 :     if( FD_LIKELY( strcmp( "", config->layout.agave_affinity ) ) ) {
     137           0 :       ushort agave_cpu[ FD_TILE_MAX ];
     138           0 :       ulong agave_cpu_cnt = fd_tile_private_cpus_parse( config->layout.agave_affinity, agave_cpu );
     139             : 
     140           0 :       for( ulong i=0UL; i<agave_cpu_cnt; i++ ) {
     141           0 :         if( FD_UNLIKELY( agave_cpu[ i ]>=fd_numa_cpu_cnt() ) )
     142           0 :           FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.agave_affinity] specifies a CPU index of %hu, but the system "
     143           0 :                        "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
     144           0 :                        "in the system.",
     145           0 :                        agave_cpu[ i ], fd_numa_cpu_cnt() ));
     146             : 
     147           0 :         for( ulong j=0UL; j<topo->tile_cnt; j++ ) {
     148           0 :           fd_topo_tile_t * tile = &topo->tiles[ j ];
     149           0 :           if( tile->cpu_idx==agave_cpu[ i ] ) FD_LOG_WARNING(( "Tile `%s:%lu` is already assigned to CPU %hu, but the CPU is also assigned to Agave. "
     150           0 :                                                                "This may cause contention between the two tiles.", tile->name, tile->kind_id, agave_cpu[ i ] ));
     151           0 :         }
     152             : 
     153           0 :         if( FD_UNLIKELY( topo->agave_affinity_cnt>FD_TILE_MAX ) ) {
     154           0 :           FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.agave_affinity] specifies more CPUs than Firedancer can use. "
     155           0 :                         "You should either reduce the number of CPUs in the affinity string." ));
     156           0 :         }
     157           0 :         topo->agave_affinity_cpu_idx[ topo->agave_affinity_cnt++ ] = agave_cpu[ i ];
     158           0 :       }
     159           0 :     }
     160           0 :   }
     161             : 
     162             :   /*                                      topo, tile_name, tile_kind_id, fseq_wksp,   link_name,      link_kind_id, reliable,            polled */
     163           6 :   FOR(net_tile_cnt) for( ulong j=0UL; j<quic_tile_cnt; j++ )
     164           3 :                        fd_topob_tile_in(  topo, "net",     i,            "metric_in", "quic_net",     j,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
     165           6 :   FOR(net_tile_cnt) for( ulong j=0UL; j<shred_tile_cnt; j++ )
     166           3 :                        fd_topob_tile_in(  topo, "net",     i,            "metric_in", "shred_net",    j,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
     167           3 :   FOR(net_tile_cnt)    fd_topob_tile_out( topo, "net",     i,                         "net_quic",     i                                                  );
     168           3 :   FOR(net_tile_cnt)    fd_topob_tile_out( topo, "net",     i,                         "net_shred",    i                                                  );
     169             : 
     170           6 :   FOR(quic_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
     171           3 :                        fd_topob_tile_in(  topo, "quic",    i,            "metric_in", "net_quic",     j,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
     172           3 :   FOR(quic_tile_cnt)   fd_topob_tile_out( topo, "quic",    i,                         "quic_verify",  i                                                  );
     173           3 :   FOR(quic_tile_cnt)   fd_topob_tile_out( topo, "quic",    i,                         "quic_net",     i                                                  );
     174             :   /* All verify tiles read from all QUIC tiles, packets are round robin. */
     175          24 :   FOR(verify_tile_cnt) for( ulong j=0UL; j<quic_tile_cnt; j++ )
     176          12 :                        fd_topob_tile_in(  topo, "verify",  i,            "metric_in", "quic_verify",  j,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers, verify tiles may be overrun */
     177          12 :   FOR(verify_tile_cnt) fd_topob_tile_out( topo, "verify",  i,                         "verify_dedup", i                                                  );
     178             :   /* Declare the single gossip link before the variable length verify-dedup links so we could have a compile-time index to the gossip link. */
     179           3 :   /**/                 fd_topob_tile_in(  topo, "dedup",   0UL,          "metric_in", "gossip_dedup", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     180          12 :   FOR(verify_tile_cnt) fd_topob_tile_in(  topo, "dedup",   0UL,          "metric_in", "verify_dedup", i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     181           3 :   /**/                 fd_topob_tile_out( topo, "dedup",   0UL,                       "dedup_resolv", 0UL                                                );
     182           3 :   FOR(resolv_tile_cnt) fd_topob_tile_in(  topo, "resolv",  i,            "metric_in", "dedup_resolv", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     183           3 :   FOR(resolv_tile_cnt) fd_topob_tile_in(  topo, "resolv",  i,            "metric_in", "replay_resol", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     184           3 :   FOR(resolv_tile_cnt) fd_topob_tile_out( topo, "resolv",  i,                         "resolv_pack",  i                                                  );
     185           3 :   /**/                 fd_topob_tile_in(  topo, "pack",    0UL,          "metric_in", "resolv_pack",  0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     186             :   /* The PoH to pack link is reliable, and must be.  The fragments going
     187             :      across here are "you became leader" which pack must respond to
     188             :      by publishing microblocks, otherwise the leader TPU will hang
     189             :      forever.
     190             : 
     191             :      It's marked as unreliable since otherwise we have a reliable credit
     192             :      loop which will also starve the pack tile.  This is OK because we
     193             :      will never send more than one leader message until the pack tile
     194             :      must acknowledge it with a packing done frag, so there will be at
     195             :      most one in flight at any time. */
     196           3 :   /**/                 fd_topob_tile_in(  topo, "pack",   0UL,           "metric_in", "poh_pack",     0UL,          FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     197           3 :                        fd_topob_tile_out( topo, "pack",   0UL,                        "pack_bank",    0UL                                                );
     198           6 :   FOR(bank_tile_cnt)   fd_topob_tile_in(  topo, "bank",   i,             "metric_in", "pack_bank",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     199           6 :   FOR(bank_tile_cnt)   fd_topob_tile_out( topo, "bank",   i,                          "bank_poh",     i                                                  );
     200           6 :   FOR(bank_tile_cnt)   fd_topob_tile_in(  topo, "poh",    0UL,           "metric_in", "bank_poh",     i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     201           3 :   if( FD_LIKELY( config->tiles.pack.use_consumed_cus ) )
     202           6 :     FOR(bank_tile_cnt) fd_topob_tile_in(  topo, "pack",   0UL,           "metric_in", "bank_poh",     i,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
     203           3 :   /**/                 fd_topob_tile_in(  topo, "poh",    0UL,           "metric_in", "stake_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     204           3 :   /**/                 fd_topob_tile_in(  topo, "poh",    0UL,           "metric_in", "pack_bank",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     205           3 :   /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "poh_shred",    0UL                                                );
     206           3 :   /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "poh_pack",     0UL                                                );
     207           6 :   FOR(shred_tile_cnt) for( ulong j=0UL; j<net_tile_cnt; j++ )
     208           3 :                        fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "net_shred",    j,            FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */
     209           3 :   FOR(shred_tile_cnt)  fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "poh_shred",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     210           3 :   FOR(shred_tile_cnt)  fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "stake_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     211           3 :   FOR(shred_tile_cnt)  fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "crds_shred",   0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     212           3 :   FOR(shred_tile_cnt)  fd_topob_tile_out( topo, "shred",  i,                          "shred_store",  i                                                  );
     213           3 :   FOR(shred_tile_cnt)  fd_topob_tile_out( topo, "shred",  i,                          "shred_net",    i                                                  );
     214           3 :   FOR(shred_tile_cnt)  fd_topob_tile_in(  topo, "store",  0UL,           "metric_in", "shred_store",  i,            FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     215             : 
     216             :   /* Sign links don't need to be reliable because they are synchronous,
     217             :      so there's at most one fragment in flight at a time anyway.  The
     218             :      sign links are also not polled by the mux, instead the tiles will
     219             :      read the sign responses out of band in a dedicated spin loop. */
     220             : 
     221           6 :   for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
     222           3 :     /**/               fd_topob_tile_in(  topo, "sign",   0UL,           "metric_in", "shred_sign",     i,          FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED   );
     223           3 :     /**/               fd_topob_tile_out( topo, "shred",  i,                          "shred_sign",     i                                                  );
     224           3 :     /**/               fd_topob_tile_in(  topo, "shred",  i,             "metric_in", "sign_shred",     i,          FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
     225           3 :     /**/               fd_topob_tile_out( topo, "sign",   0UL,                        "sign_shred",     i                                                  );
     226           3 :   }
     227             : 
     228             :   /* PoH tile represents the Agave address space, so it's
     229             :      responsible for publishing Agave provided data to
     230             :      these links. */
     231             :   /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "gossip_dedup", 0UL                                                  );
     232           3 :   /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "stake_out",    0UL                                                  );
     233           3 :   /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "crds_shred",   0UL                                                  );
     234           3 :   /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "replay_resol", 0UL                                                );
     235             : 
     236             :   /* For now the only plugin consumer is the GUI */
     237           3 :   int plugins_enabled = config->tiles.gui.enabled;
     238           3 :   if( FD_LIKELY( plugins_enabled ) ) {
     239           0 :     fd_topob_wksp( topo, "plugin_in"    );
     240           0 :     fd_topob_wksp( topo, "plugin_out"   );
     241           0 :     fd_topob_wksp( topo, "plugin"       );
     242             : 
     243             :     /**/                 fd_topob_link( topo, "plugin_out",   "plugin_out",   0,        128UL,                                    8UL+40200UL*(58UL+12UL*34UL), 1UL );
     244           0 :     /**/                 fd_topob_link( topo, "replay_plugi", "plugin_in",    0,        128UL,                                    4098*8UL,               1UL );
     245           0 :     /**/                 fd_topob_link( topo, "gossip_plugi", "plugin_in",    0,        128UL,                                    8UL+40200UL*(58UL+12UL*34UL), 1UL );
     246           0 :     /**/                 fd_topob_link( topo, "poh_plugin",   "plugin_in",    0,        128UL,                                    16UL,                   1UL );
     247           0 :     /**/                 fd_topob_link( topo, "startp_plugi", "plugin_in",    0,        128UL,                                    56UL,                   1UL );
     248           0 :     /**/                 fd_topob_link( topo, "votel_plugin", "plugin_in",    0,        128UL,                                    8UL,                    1UL );
     249             : 
     250             :     /**/                 fd_topob_tile( topo, "plugin",  "plugin",  "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     251             : 
     252             :     /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "replay_plugi", 0UL                                                  );
     253           0 :     /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "gossip_plugi", 0UL                                                  );
     254           0 :     /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "poh_plugin",   0UL                                                  );
     255           0 :     /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "startp_plugi", 0UL                                                  );
     256           0 :     /**/                 fd_topob_tile_out( topo, "poh",    0UL,                        "votel_plugin", 0UL                                                  );
     257           0 :     /**/                 fd_topob_tile_out( topo, "plugin", 0UL,                        "plugin_out", 0UL                                                    );
     258             : 
     259           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "replay_plugi", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     260           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "gossip_plugi", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     261           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "stake_out",    0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     262           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "poh_plugin",   0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     263           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "startp_plugi", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     264           0 :     /**/                 fd_topob_tile_in(  topo, "plugin", 0UL,           "metric_in", "votel_plugin", 0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     265           0 :   }
     266             : 
     267           3 :   if( FD_LIKELY( config->tiles.gui.enabled ) ) {
     268           0 :     fd_topob_wksp( topo, "gui"          );
     269           0 :     /**/                 fd_topob_tile( topo, "gui",     "gui",     "metric_in",  tile_to_cpu[ topo->tile_cnt ], 0 );
     270           0 :     /**/                 fd_topob_tile_in(  topo, "gui",    0UL,           "metric_in", "plugin_out",   0UL,          FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     271           0 :   }
     272             : 
     273           3 :   if( FD_LIKELY( !is_auto_affinity ) ) {
     274           0 :     if( FD_UNLIKELY( affinity_tile_cnt<topo->tile_cnt ) )
     275           0 :       FD_LOG_ERR(( "The topology you are using has %lu tiles, but the CPU affinity specified in the config tile as [layout.affinity] only provides for %lu cores. "
     276           0 :                    "You should either increase the number of cores dedicated to Firedancer in the affinity string, or decrease the number of cores needed by reducing "
     277           0 :                    "the total tile count. You can reduce the tile count by decreasing individual tile counts in the [layout] section of the configuration file.",
     278           0 :                    topo->tile_cnt, affinity_tile_cnt ));
     279           0 :     if( FD_UNLIKELY( affinity_tile_cnt>topo->tile_cnt ) )
     280           0 :       FD_LOG_WARNING(( "The topology you are using has %lu tiles, but the CPU affinity specified in the config tile as [layout.affinity] provides for %lu cores. "
     281           0 :                        "Not all cores in the affinity will be used by Firedancer. You may wish to increase the number of tiles in the system by increasing "
     282           0 :                        "individual tile counts in the [layout] section of the configuration file.",
     283           0 :                        topo->tile_cnt, affinity_tile_cnt ));
     284             : 
     285           0 :     if( FD_LIKELY( strcmp( "", config->layout.agave_affinity ) ) ) {
     286           0 :       ushort agave_cpu[ FD_TILE_MAX ];
     287           0 :       ulong agave_cpu_cnt = fd_tile_private_cpus_parse( config->layout.agave_affinity, agave_cpu );
     288             : 
     289           0 :       for( ulong i=0UL; i<agave_cpu_cnt; i++ ) {
     290           0 :         if( FD_UNLIKELY( agave_cpu[ i ]>=fd_numa_cpu_cnt() ) )
     291           0 :           FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.agave_affinity] specifies a CPU index of %hu, but the system "
     292           0 :                        "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
     293           0 :                        "in the system.",
     294           0 :                        agave_cpu[ i ], fd_numa_cpu_cnt() ));
     295             : 
     296           0 :         for( ulong j=0UL; j<topo->tile_cnt; j++ ) {
     297           0 :           fd_topo_tile_t * tile = &topo->tiles[ j ];
     298           0 :           if( tile->cpu_idx==agave_cpu[ i ] ) FD_LOG_WARNING(( "Tile `%s:%lu` is already assigned to CPU %hu, but the CPU is also assigned to Agave. "
     299           0 :                                                                "This may cause contention between the two tiles.", tile->name, tile->kind_id, agave_cpu[ i ] ));
     300           0 :         }
     301             : 
     302           0 :         if( FD_UNLIKELY( topo->agave_affinity_cnt>FD_TILE_MAX ) ) {
     303           0 :           FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.agave_affinity] specifies more CPUs than Firedancer can use. "
     304           0 :                         "You should either reduce the number of CPUs in the affinity string." ));
     305           0 :         }
     306           0 :         topo->agave_affinity_cpu_idx[ topo->agave_affinity_cnt++ ] = agave_cpu[ i ];
     307           0 :       }
     308           0 :     }
     309           0 :   }
     310             : 
     311             :   /* There is a special fseq that sits between the pack, bank, and poh
     312             :      tiles to indicate when the bank/poh tiles are done processing a
     313             :      microblock.  Pack uses this to determine when to "unlock" accounts
     314             :      that it marked as locked because they were being used. */
     315             : 
     316           9 :   for( ulong i=0UL; i<bank_tile_cnt; i++ ) {
     317           6 :     fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "bank_busy" );
     318             : 
     319           6 :     fd_topo_tile_t * poh_tile = &topo->tiles[ fd_topo_find_tile( topo, "poh", 0UL ) ];
     320           6 :     fd_topo_tile_t * pack_tile = &topo->tiles[ fd_topo_find_tile( topo, "pack", 0UL ) ];
     321           6 :     fd_topob_tile_uses( topo, poh_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     322           6 :     fd_topob_tile_uses( topo, pack_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
     323           6 :     FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "bank_busy.%lu", i ) );
     324           6 :   }
     325             : 
     326             :   /* There's another special fseq that's used to communicate the shred
     327             :      version from the Agave boot path to the shred tile. */
     328           3 :   fd_topo_obj_t * poh_shred_obj = fd_topob_obj( topo, "fseq", "poh_shred" );
     329           3 :   fd_topo_tile_t * poh_tile = &topo->tiles[ fd_topo_find_tile( topo, "poh", 0UL ) ];
     330           3 :   fd_topob_tile_uses( topo, poh_tile, poh_shred_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     331           6 :   for( ulong i=0UL; i<shred_tile_cnt; i++ ) {
     332           3 :     fd_topo_tile_t * shred_tile = &topo->tiles[ fd_topo_find_tile( topo, "shred", i ) ];
     333           3 :     fd_topob_tile_uses( topo, shred_tile, poh_shred_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
     334           3 :   }
     335           3 :   FD_TEST( fd_pod_insertf_ulong( topo->props, poh_shred_obj->id, "poh_shred" ) );
     336             : 
     337          54 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     338          51 :     fd_topo_tile_t * tile = &topo->tiles[ i ];
     339             : 
     340          51 :     if( FD_UNLIKELY( !strcmp( tile->name, "net" ) ) ) {
     341           3 :       strncpy( tile->net.interface,    config->tiles.net.interface, sizeof(tile->net.interface) );
     342           3 :       memcpy(  tile->net.src_mac_addr, config->tiles.net.mac_addr,  6UL );
     343             : 
     344           3 :       tile->net.xdp_aio_depth     = config->tiles.net.xdp_aio_depth;
     345           3 :       tile->net.xdp_rx_queue_size = config->tiles.net.xdp_rx_queue_size;
     346           3 :       tile->net.xdp_tx_queue_size = config->tiles.net.xdp_tx_queue_size;
     347           3 :       tile->net.src_ip_addr       = config->tiles.net.ip_addr;
     348           3 :       tile->net.zero_copy         = !!strcmp( config->tiles.net.xdp_mode, "skb" ); /* disable zc for skb */
     349           3 :       fd_memset( tile->net.xdp_mode, 0, 4 );
     350           3 :       fd_memcpy( tile->net.xdp_mode, config->tiles.net.xdp_mode, strnlen( config->tiles.net.xdp_mode, 3 ) );  /* GCC complains about strncpy */
     351             : 
     352           3 :       tile->net.shred_listen_port              = config->tiles.shred.shred_listen_port;
     353           3 :       tile->net.quic_transaction_listen_port   = config->tiles.quic.quic_transaction_listen_port;
     354           3 :       tile->net.legacy_transaction_listen_port = config->tiles.quic.regular_transaction_listen_port;
     355             : 
     356             :       /* multihome support */
     357           3 :       ulong multi_cnt = tile->net.multihome_ip_addrs_cnt = config->tiles.net.multihome_ip_addrs_cnt;
     358           3 :       for( ulong j = 0; j < multi_cnt; ++j ) {
     359           0 :         tile->net.multihome_ip_addrs[j] = config->tiles.net.multihome_ip4_addrs[j];
     360           0 :       }
     361          48 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "quic" ) ) ) {
     362           3 :       fd_memcpy( tile->quic.src_mac_addr, config->tiles.net.mac_addr, 6 );
     363           3 :       strncpy( tile->quic.identity_key_path, config->consensus.identity_path, sizeof(tile->quic.identity_key_path) );
     364             : 
     365           3 :       tile->quic.depth                          = topo->links[ tile->out_link_id[ 0 ] ].depth;
     366           3 :       tile->quic.reasm_cnt                      = config->tiles.quic.txn_reassembly_count;
     367           3 :       tile->quic.max_concurrent_connections     = config->tiles.quic.max_concurrent_connections;
     368           3 :       tile->quic.max_concurrent_handshakes      = config->tiles.quic.max_concurrent_handshakes;
     369           3 :       tile->quic.max_inflight_quic_packets      = config->tiles.quic.max_inflight_quic_packets;
     370           3 :       tile->quic.ip_addr                        = config->tiles.net.ip_addr;
     371           3 :       tile->quic.quic_transaction_listen_port   = config->tiles.quic.quic_transaction_listen_port;
     372           3 :       tile->quic.idle_timeout_millis            = config->tiles.quic.idle_timeout_millis;
     373           3 :       tile->quic.ack_delay_millis               = config->tiles.quic.ack_delay_millis;
     374           3 :       tile->quic.retry                          = config->tiles.quic.retry;
     375           3 :       tile->quic.max_concurrent_streams_per_connection = config->tiles.quic.max_concurrent_streams_per_connection;
     376             : 
     377          45 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "verify" ) ) ) {
     378             : 
     379          33 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "dedup" ) ) ) {
     380           3 :       tile->dedup.tcache_depth = config->tiles.dedup.signature_cache_size;
     381             : 
     382          30 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "resolv" ) ) ) {
     383             : 
     384          27 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "pack" ) ) ) {
     385           3 :       strncpy( tile->pack.identity_key_path, config->consensus.identity_path, sizeof(tile->pack.identity_key_path) );
     386             : 
     387           3 :       tile->pack.max_pending_transactions      = config->tiles.pack.max_pending_transactions;
     388           3 :       tile->pack.bank_tile_count               = config->layout.bank_tile_count;
     389           3 :       tile->pack.larger_max_cost_per_block     = config->development.bench.larger_max_cost_per_block;
     390           3 :       tile->pack.larger_shred_limits_per_block = config->development.bench.larger_shred_limits_per_block;
     391           3 :       tile->pack.use_consumed_cus              = config->tiles.pack.use_consumed_cus;
     392             : 
     393          24 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "bank" ) ) ) {
     394             : 
     395          18 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "poh" ) ) ) {
     396           3 :       strncpy( tile->poh.identity_key_path, config->consensus.identity_path, sizeof(tile->poh.identity_key_path) );
     397             : 
     398           3 :       tile->poh.plugins_enabled = plugins_enabled;
     399           3 :       tile->poh.bank_cnt = config->layout.bank_tile_count;
     400             : 
     401          15 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "shred" ) ) ) {
     402           3 :       fd_memcpy( tile->shred.src_mac_addr, config->tiles.net.mac_addr, 6 );
     403           3 :       strncpy( tile->shred.identity_key_path, config->consensus.identity_path, sizeof(tile->shred.identity_key_path) );
     404             : 
     405           3 :       tile->shred.depth                         = topo->links[ tile->out_link_id[ 0 ] ].depth;
     406           3 :       tile->shred.ip_addr                       = config->tiles.net.ip_addr;
     407           3 :       tile->shred.fec_resolver_depth            = config->tiles.shred.max_pending_shred_sets;
     408           3 :       tile->shred.expected_shred_version        = config->consensus.expected_shred_version;
     409           3 :       tile->shred.shred_listen_port             = config->tiles.shred.shred_listen_port;
     410           3 :       tile->shred.larger_shred_limits_per_block = config->development.bench.larger_shred_limits_per_block;
     411             : 
     412          12 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "store" ) ) ) {
     413           3 :       tile->store.disable_blockstore_from_slot = config->development.bench.disable_blockstore_from_slot;
     414             : 
     415           9 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "sign" ) ) ) {
     416           3 :       strncpy( tile->sign.identity_key_path, config->consensus.identity_path, sizeof(tile->sign.identity_key_path) );
     417             : 
     418           6 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "metric" ) ) ) {
     419           3 :       if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.metric.prometheus_listen_address, &tile->metric.prometheus_listen_addr ) ) )
     420           0 :         FD_LOG_ERR(( "failed to parse prometheus listen address `%s`", config->tiles.metric.prometheus_listen_address ));
     421           3 :       tile->metric.prometheus_listen_port = config->tiles.metric.prometheus_listen_port;
     422             : 
     423           3 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "cswtch" ) ) ) {
     424             : 
     425           3 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "gui" ) ) ) {
     426           0 :       if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.gui.gui_listen_address, &tile->gui.listen_addr ) ) )
     427           0 :         FD_LOG_ERR(( "failed to parse gui listen address `%s`", config->tiles.gui.gui_listen_address ));
     428           0 :       tile->gui.listen_port = config->tiles.gui.gui_listen_port;
     429           0 :       tile->gui.is_voting = strcmp( config->consensus.vote_account_path, "" );
     430           0 :       strncpy( tile->gui.cluster, config->cluster, sizeof(tile->gui.cluster) );
     431           0 :       strncpy( tile->gui.identity_key_path, config->consensus.identity_path, sizeof(tile->gui.identity_key_path) );
     432             : 
     433           0 :     } else if( FD_UNLIKELY( !strcmp( tile->name, "plugin" ) ) ) {
     434             : 
     435           0 :     } else {
     436           0 :       FD_LOG_ERR(( "unknown tile name %lu `%s`", i, tile->name ));
     437           0 :     }
     438          51 :   }
     439             : 
     440           3 :   if( FD_UNLIKELY( is_auto_affinity ) ) fd_topob_auto_layout( topo );
     441             : 
     442           3 :   fd_topob_finish( topo, fdctl_obj_align, fdctl_obj_footprint, fdctl_obj_loose );
     443           3 :   config->topo = *topo;
     444           3 : }

Generated by: LCOV version 1.14