LCOV - code coverage report
Current view: top level - disco/topo - fd_topo.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 160 0.0 %
Date: 2026-11-11 12:40:43 Functions: 0 3834 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_disco_topo_fd_topo_h
       2             : #define HEADER_fd_src_disco_topo_fd_topo_h
       3             : 
       4             : #include "../stem/fd_stem.h"
       5             : #include "../../tango/fd_tango.h"
       6             : #include "../../waltz/xdp/fd_xdp1.h"
       7             : #include "../../waltz/http/fd_url.h"
       8             : #include "../../ballet/base58/fd_base58.h"
       9             : #include "../../flamenco/fd_flamenco_base.h"
      10             : #include "../../util/net/fd_net_headers.h"
      11             : #include "../../util/net/fd_ip6.h"
      12             : #include "../pack/fd_pack_acct_blocklist.h"
      13             : #include "../keyguard/fd_keyguard.h"
      14             : 
      15             : /* Maximum number of workspaces that may be present in a topology. */
      16             : #define FD_TOPO_MAX_WKSPS          ( 256UL)
      17             : /* Maximum number of links that may be present in a topology. */
      18           0 : #define FD_TOPO_MAX_LINKS          (1024UL)
      19             : /* Maximum number of tiles that may be present in a topology. */
      20           0 : #define FD_TOPO_MAX_TILES          ( 256UL)
      21             : /* Maximum number of objects that may be present in a topology. */
      22             : #define FD_TOPO_MAX_OBJS           (4096UL)
      23             : /* Maximum number of links that may go into any one tile in the
      24             :    topology. */
      25           0 : #define FD_TOPO_MAX_TILE_IN_LINKS  ( 256UL)
      26             : /* Maximum number of links that a tile may write to. */
      27             : #define FD_TOPO_MAX_TILE_OUT_LINKS (  64UL)
      28             : /* Maximum number of objects that a tile can use. */
      29             : #define FD_TOPO_MAX_TILE_OBJS      (1024UL)
      30             : 
      31             : FD_STATIC_ASSERT( FD_SLEEP_LINK_MAX==FD_TOPO_MAX_LINKS,          sleep_limits );
      32             : FD_STATIC_ASSERT( FD_SLEEP_IN_MAX  ==FD_TOPO_MAX_TILE_IN_LINKS,  sleep_limits );
      33             : FD_STATIC_ASSERT( FD_SLEEP_OUT_MAX ==FD_TOPO_MAX_TILE_OUT_LINKS, sleep_limits );
      34             : 
      35             : /* Maximum number of additional ip addresses */
      36             : #define FD_NET_MAX_SRC_ADDR 4
      37             : 
      38             : /* Maximum number of additional destinations for leader shreds and for retransmitted shreds */
      39             : #define FD_TOPO_ADTL_DESTS_MAX ( 32UL)
      40             : 
      41           0 : #define FD_TOPO_CORE_DUMP_LEVEL_DISABLED (0)
      42           0 : #define FD_TOPO_CORE_DUMP_LEVEL_MINIMAL  (1)
      43           0 : #define FD_TOPO_CORE_DUMP_LEVEL_REGULAR  (2)
      44           0 : #define FD_TOPO_CORE_DUMP_LEVEL_FULL     (3)
      45           0 : #define FD_TOPO_CORE_DUMP_LEVEL_NEVER    (4)
      46             : 
      47             : /* A workspace is a Firedancer specific memory management structure that
      48             :    sits on top of 1 or more memory mapped gigantic or huge pages mounted
      49             :    to the hugetlbfs. */
      50             : typedef struct {
      51             :   ulong id;           /* The ID of this workspace.  Indexed from [0, wksp_cnt).  When placed in a topology, the ID must be the index of the workspace in the workspaces list. */
      52             :   char  name[ 14UL ]; /* The name of this workspace, like "pack".  There can be at most one of each workspace name in a topology. */
      53             : 
      54             :   ulong numa_idx;     /* The index of the NUMA node on the system that this workspace should be allocated from. */
      55             : 
      56             :   ulong min_part_max; /* Artificially raise part_max */
      57             :   ulong min_loose_sz; /* Artificially raise loose footprint */
      58             : 
      59             :   /* Computed fields.  These are not supplied as configuration but calculated as needed. */
      60             :   struct {
      61             :     ulong page_sz;  /* The size of the pages that this workspace is backed by.  One of FD_PAGE_SIZE_*. */
      62             :     ulong page_cnt; /* The number of pages that must be mapped to this workspace to store all the data needed by consumers. */
      63             :     ulong part_max; /* The maximum number of partitions in the underlying workspace.  There can only be this many allocations made at any one time. */
      64             : 
      65             :     int core_dump_level; /* The core dump level required to be set in the application configuration to have this workspace appear in core dumps. */
      66             : 
      67             :     fd_wksp_t * wksp;            /* The workspace memory in the local process. */
      68             :     ulong       known_footprint; /* Total size in bytes of all data in Firedancer that will be stored in this workspace at startup. */
      69             :     ulong       total_footprint; /* Total size in bytes of all data in Firedancer that could be stored in this workspace, includes known data and loose data. */
      70             :   };
      71             : } fd_topo_wksp_t;
      72             : 
      73             : /* A link is an mcache in a workspace that has one producer and one or
      74             :    more consumers. A link may optionally also have a dcache, that holds
      75             :    fragments referred to by the mcache entries.
      76             : 
      77             :    A link belongs to exactly one workspace.  A link has exactly one
      78             :    producer, and 1 or more consumers.  Each consumer is either reliable
      79             :    or not reliable.  A link has a depth and a MTU, which correspond to
      80             :    the depth and MTU of the mcache and dcache respectively.  A MTU of
      81             :    zero means no dcache is needed, as there is no data. */
      82             : typedef struct {
      83             :   ulong id;           /* The ID of this link.  Indexed from [0, link_cnt).  When placed in a topology, the ID must be the index of the link in the links list. */
      84             :   char  name[ 14UL ]; /* The name of this link, like "pack_execle". There can be multiple of each link name in a topology. */
      85             :   ulong kind_id;      /* The ID of this link within its name.  If there are N links of a particular name, they have IDs [0, N).  The pair (name, kind_id) uniquely identifies a link, as does "id" on its own. */
      86             : 
      87             :   ulong depth;    /* The depth of the mcache representing the link. */
      88             :   ulong mtu;      /* The MTU of data fragments in the mcache.  A value of 0 means there is no dcache. */
      89             :   ulong burst;    /* The max amount of MTU sized data fragments that might be bursted to the dcache. */
      90             : 
      91             :   ulong mcache_obj_id;
      92             :   ulong dcache_obj_id;
      93             : 
      94             :   /* Computed fields.  These are not supplied as configuration but calculated as needed. */
      95             :   struct {
      96             :     fd_frag_meta_t * mcache; /* The mcache of this link. */
      97             :     void *           dcache; /* The dcache of this link, if it has one. */
      98             :   };
      99             : 
     100             :   uint permit_no_consumers : 1;  /* Permit a topology where this link has no consumers */
     101             :   uint permit_no_producers : 1;  /* Permit a topology where this link has no producers */
     102             : } fd_topo_link_t;
     103             : 
     104             : struct fd_topo_net_tile {
     105             :   ulong umem_dcache_obj_id;  /* dcache for network UMEM frames */
     106             :   uint  bind_address;
     107             : 
     108             :   ushort shred_listen_port;
     109             :   ushort quic_transaction_listen_port;
     110             :   ushort legacy_transaction_listen_port;
     111             :   ushort gossip_listen_port;
     112             :   ushort repair_client_listen_port;
     113             :   ushort repair_serve_listen_port;
     114             :   ushort votor_quic_client_listen_port;
     115             :   ushort votor_quic_server_listen_port;
     116             : };
     117             : typedef struct fd_topo_net_tile fd_topo_net_tile_t;
     118             : 
     119             : /* A tile is a unique process that is spawned by Firedancer to represent
     120             :    one thread of execution.  Firedancer sandboxes all tiles to their own
     121             :    process for security reasons.
     122             : 
     123             :    A tile belongs to exactly one workspace.  A tile is a consumer of 0
     124             :    or more links, it's inputs.  A tile is a producer of 0 or more output
     125             :    links.
     126             : 
     127             :    All input links will be automatically polled by the tile
     128             :    infrastructure, and output links will automatically source and manage
     129             :    credits from consumers. */
     130             : struct fd_topo_tile {
     131             :   ulong id;                     /* The ID of this tile.  Indexed from [0, tile_cnt).  When placed in a topology, the ID must be the index of the tile in the tiles list. */
     132             :   char  name[ 7UL ];            /* The name of this tile.  There can be multiple of each tile name in a topology. */
     133             :   ulong kind_id;                /* The ID of this tile within its name.  If there are n tile of a particular name, they have IDs [0, N).  The pair (name, kind_id) uniquely identifies a tile, as does "id" on its own. */
     134             : 
     135             :   int   is_waker_client;        /* Tile has file descriptors which must be serviced by the external waker tile. */
     136             :   int   allow_shutdown;         /* If the tile is allowed to shutdown gracefully.  If false, when the tile exits it will tear down the entire application. */
     137             : 
     138             :   ulong cpu_idx;                /* The CPU index to pin the tile on.  A value of ULONG_MAX or more indicates the tile should be floating and not pinned to a core. */
     139             :   int   floats;                 /* Scheduled by the kernel over the CPUs of the floating tiles on its NUMA node, never a pinned tile's CPU, instead of pinned to cpu_idx (efficient mode).  cpu_idx still places memory and isolation, and is the fallback when no such CPU remains. */
     140             :   int   sleep_eventfd;          /* Parks in epoll on its own fds and is woken through the eventfd FD_SLEEP_EVENTFD( id ), not FUTEX_WAKE (efficient mode only) */
     141             : 
     142             :   ulong waker_client_idx;       /* Client slot in the fixed inherited fd range (inner epoll fd FD_WAKER_INNER_FD( idx )), or ULONG_MAX if not a waker client */
     143             :   ulong waker_fseq_obj_id;      /* fseq object holding the tile's waker readiness word or ULONG_MAX */
     144             : 
     145             :   ulong in_cnt;                 /* The number of links that this tile reads from. */
     146             :   ulong in_link_id[ FD_TOPO_MAX_TILE_IN_LINKS ];       /* The link_id of each link that this tile reads from, indexed in [0, in_cnt). */
     147             :   int   in_link_reliable[ FD_TOPO_MAX_TILE_IN_LINKS ]; /* If each link that this tile reads from is a reliable or unreliable consumer, indexed in [0, in_cnt). */
     148             :   int   in_link_poll[ FD_TOPO_MAX_TILE_IN_LINKS ];     /* If each link that this tile reads from should be polled by the tile infrastructure, indexed in [0, in_cnt).
     149             :                                                           If the link is not polled, the tile will not receive frags for it and the tile writer is responsible for
     150             :                                                           reading from the link.  The link must be marked as unreliable as it is not flow controlled. */
     151             : 
     152             :   ulong out_cnt;                                   /* The number of links that this tile writes to. */
     153             :   ulong out_link_id[ FD_TOPO_MAX_TILE_OUT_LINKS ]; /* The link_id of each link that this tile writes to, indexed in [0, link_cnt). */
     154             : 
     155             :   ulong event_link_id; /* If not ULONG_MAX, the link_id of a dedicated unreliable link to the event tile that this tile reports
     156             :                           telemetry events on via the thread-local fd_event_report_* macros.  This link is deliberately NOT part
     157             :                           of out_link_id[] / out_cnt: it is written directly (outside fd_stem) by the thread-local reporter. */
     158             : 
     159             :   ulong tile_obj_id;
     160             :   ulong metrics_obj_id;
     161             :   ulong id_keyswitch_obj_id; /* keyswitch object id for identity key updates */
     162             :   ulong av_keyswitch_obj_id; /* keyswitch object id for authority key updates */
     163             :   ulong in_link_fseq_obj_id[ FD_TOPO_MAX_TILE_IN_LINKS ];
     164             : 
     165             :   ulong uses_obj_cnt;
     166             :   ulong uses_obj_id[ FD_TOPO_MAX_TILE_OBJS ];
     167             :   int   uses_obj_mode[ FD_TOPO_MAX_TILE_OBJS ];
     168             : 
     169             :   /* Computed fields.  These are not supplied as configuration but calculated as needed. */
     170             :   struct {
     171             :     ulong *    metrics; /* The shared memory for metrics that this tile should write.  Consumer by monitoring and metrics writing tiles. */
     172             : 
     173             :     /* The fseq of each link that this tile reads from.  Multiple fseqs
     174             :        may point to the link, if there are multiple consumers.  An fseq
     175             :        can be uniquely identified via (link_id, tile_id), or (link_kind,
     176             :        link_kind_id, tile_kind, tile_kind_id) */
     177             :     ulong *    in_link_fseq[ FD_TOPO_MAX_TILE_IN_LINKS ];
     178             :   };
     179             : 
     180             :   /* Configuration fields.  These are required to be known by the topology so it can determine the
     181             :      total size of Firedancer in memory. */
     182             :   union {
     183             :     fd_topo_net_tile_t net;
     184             : 
     185             :     struct {
     186             :       fd_topo_net_tile_t net;
     187             : 
     188             :       char if_virt[ 16 ];  /* device name (virtual, for routing) */
     189             :       char if_phys[ 16 ];  /* device name (physical, for RX/TX) */
     190             :       uint if_queue;       /* device queue index */
     191             : 
     192             :       /* xdp specific options */
     193             :       ulong  xdp_rx_queue_size;
     194             :       ulong  xdp_tx_queue_size;
     195             :       ulong  free_ring_depth;
     196             :       long   tx_flush_timeout_ns;
     197             :       char   xdp_mode[8];
     198             :       int    zero_copy;
     199             : 
     200             :       char poll_mode[ 16 ]; /* "softirq" or "prefbusy" */
     201             : 
     202             :       ulong netdev_tbl_obj_id;
     203             : 
     204             :       ulong route_max;
     205             :       ulong route_peer_max;
     206             :       ulong route_peer_seed;
     207             :       ulong neigh4_obj_id;         /* neigh4 hash map */
     208             :     } xdp;
     209             : 
     210             :     struct {
     211             :       fd_topo_net_tile_t net;
     212             : 
     213             :       char  if_name[ 16 ];
     214             :       uint  rx_queue_size;
     215             :       uint  tx_queue_size;
     216             :       uint  batch_size;
     217             : 
     218             :       ulong netdev_tbl_obj_id;
     219             :       ulong route_max;
     220             :       ulong route_peer_max;
     221             :       ulong route_peer_seed;
     222             :       ulong neigh4_obj_id;
     223             :     } mlx5;
     224             : 
     225             :     struct {
     226             :       fd_topo_net_tile_t net;
     227             : 
     228             :       char  if_name[ 16 ];
     229             :       char  members[ 16 ][ 16 ];
     230             :       ulong member_cnt;
     231             :       uint  rx_queue_size;
     232             :       uint  tx_queue_size;
     233             : 
     234             :       ulong netdev_tbl_obj_id;
     235             :       ulong route_max;
     236             :       ulong route_peer_max;
     237             :       ulong route_peer_seed;
     238             :       ulong neigh4_obj_id;
     239             :     } iavf;
     240             : 
     241             :     struct {
     242             :       fd_topo_net_tile_t net;
     243             :       /* sock specific options */
     244             :       int   so_sndbuf;
     245             :       int   so_rcvbuf;
     246             :       int   only_recv_lo;
     247             :       ulong net_tile_id;
     248             :     } sock;
     249             : 
     250             :     struct {
     251             :       ulong netdev_tbl_obj_id;
     252             :       ulong route_max;
     253             :       ulong route_peer_max;
     254             :       char  neigh_if[ 16 ];        /* neigh4 interface name */
     255             :       ulong neigh4_obj_id;         /* neigh4 hash map */
     256             :     } netlink;
     257             : 
     258             :     struct {
     259             :       char identity_key_path[ PATH_MAX ];
     260             :     } admin;
     261             : 
     262             :     struct {
     263             :       char   identity_key_path[ PATH_MAX ]; /* the key this machine boots under */
     264             :       char   target_key_path[ PATH_MAX ];   /* the identity failover hands off, [paths.identity_key] */
     265             :       int    listen;      /* open the network listener so we can hand over our identity to another machine */
     266             :       uint   listen_addr; /* network byte order */
     267             :       ushort port;
     268             : 
     269             :       char          gossip_host[ FD_FQDN_BUF_MAX ];
     270             :       fd_ip4_port_t gossip_addr; /* our own gossip socket, gossip_host overrides the address */
     271             :     } failov;
     272             : 
     273           0 : #define FD_TOPO_GOSSIP_ENTRYPOINTS_MAX 16UL
     274             : 
     275             :     struct {
     276             :       char identity_key_path[ PATH_MAX ];
     277             : 
     278             :       ulong entrypoints_cnt;
     279             :       char  entrypoints[ FD_TOPO_GOSSIP_ENTRYPOINTS_MAX ][ FD_HOSTPORT_BUF_MAX ];
     280             : 
     281             :       long boot_timestamp_nanos;
     282             : 
     283             :       ulong tcache_depth;
     284             : 
     285             :       ushort shred_version;
     286             :       int allow_private_address;
     287             : 
     288             :       char          gossip_host[ FD_FQDN_BUF_MAX ];
     289             :       fd_ip4_port_t gossip_addr;
     290             :       fd_ip4_port_t src_addr;
     291             :     } gossvf;
     292             : 
     293             :     struct {
     294             :       char identity_key_path[ PATH_MAX ];
     295             : 
     296             :       ulong entrypoints_cnt;
     297             :       char  entrypoints[ FD_TOPO_GOSSIP_ENTRYPOINTS_MAX ][ FD_HOSTPORT_BUF_MAX ];
     298             : 
     299             :       long boot_timestamp_nanos;
     300             : 
     301             :       char   gossip_host[ FD_FQDN_BUF_MAX ];
     302             :       uint   net_ip_addr; /* net.ip_addr fallback when gossip_host empty */
     303             :       uint   ip_addr;
     304             :       uint   bind_ip_addr;
     305             :       ushort expected_shred_version;
     306             : 
     307             :       ulong  max_entries;
     308             :       ulong  max_purged;
     309             :       ulong  max_failed;
     310             : 
     311             :       ulong wait_for_supermajority_at_slot;
     312             :       int   wait_for_supermajority_hash_is_zero;
     313             : 
     314             :       struct {
     315             :         ushort gossip;
     316             :         ushort tvu;
     317             :         ushort tvu_quic;
     318             :         ushort tpu;
     319             :         ushort tpu_quic;
     320             :         ushort repair;
     321             :         ushort rserve;
     322             :         ushort votor;
     323             :       } ports;
     324             :     } gossip;
     325             : 
     326             :     struct {
     327             :       uint   out_depth;
     328             :       uint   reasm_cnt;
     329             :       ulong  max_concurrent_connections;
     330             :       ulong  max_concurrent_handshakes;
     331             :       ushort quic_transaction_listen_port;
     332             :       long   idle_timeout_millis;
     333             :       uint   ack_delay_millis;
     334             :       int    retry;
     335             :       char   key_log_path[ PATH_MAX ];
     336             :     } quic;
     337             : 
     338             :     struct {
     339             :       ulong tcache_depth;
     340             :     } verify;
     341             : 
     342             :     struct {
     343             :       ulong tcache_depth;
     344             :     } dedup;
     345             : 
     346             :     struct {
     347             :       char  url[ FD_URL_MAX ];
     348             :       ulong url_len;
     349             :       char  sni[ FD_SNI_BUF_MAX ];
     350             :       ulong sni_len;
     351             :       char  identity_key_path[ PATH_MAX ];
     352             :       char  key_log_path[ PATH_MAX ];
     353             :       ulong buf_sz;
     354             :       ulong keepalive_interval_nanos;
     355             :       uchar tls_cert_verify : 1;
     356             :     } bundle;
     357             : 
     358             :     struct {
     359             :       char   url[ FD_URL_MAX ];
     360             :       char   identity_key_path[ PATH_MAX ];
     361             :       char   action[ 16 ];
     362             :       uchar  genesis_hash[ 32 ];
     363             :       ushort shred_version;
     364             : 
     365             :       char   accounts_path [ PATH_MAX ];
     366             :       char   snapshots_path[ PATH_MAX ];
     367             :       char   log_path      [ PATH_MAX ];
     368             :       char   shredb_path   [ PATH_MAX ];
     369             :       char   guidb_path    [ PATH_MAX ];
     370             :       char   net_interface [ 16 ];
     371             :       long   boot_timestamp_nanos;
     372             :       ulong  launch_cpus[ 1024UL/64UL ];
     373             :       char   launch_cgroup[ PATH_MAX ];
     374             :       ulong  tx_rate_mbps;
     375             :     } event;
     376             : 
     377             :     struct {
     378             :       ulong max_pending_transactions;
     379             :       ulong execle_tile_count;
     380             :       ulong max_cost_per_block;
     381             :       ulong max_shreds_per_block;
     382             :       ulong bench_max_shreds_per_block; /* [development.bench], floors the leader's per-slot shred limit */
     383             :       int   use_consumed_cus;
     384             :       int   schedule_strategy;
     385             :       struct {
     386             :         int   enabled;
     387             :         uchar tip_distribution_program_addr[ 32 ];
     388             :         uchar tip_payment_program_addr[ 32 ];
     389             :         uchar tip_distribution_authority[ 32 ];
     390             :         ulong commission_bps;
     391             :         char  identity_key_path[ PATH_MAX ];
     392             :         char  vote_account_path[ PATH_MAX ]; /* or pubkey is okay */
     393             :       } bundle;
     394             :       ulong acct_blocklist_cnt;
     395             :       fd_pubkey_t acct_blocklist[ FD_PACK_ACCT_BLOCKLIST_MAX ];
     396             :     } pack;
     397             : 
     398             :     struct {
     399             :       ulong execle_cnt;
     400             :       char  identity_key_path[ PATH_MAX ];
     401             :       ulong max_txn_per_slot;
     402             :     } poh;
     403             : 
     404             :     struct {
     405             :       ulong execle_cnt;
     406             :       char  identity_key_path[ PATH_MAX ];
     407             :       ulong max_txn_per_slot;
     408             :     } motor;
     409             : 
     410             :     struct {
     411             :       ulong             fec_exposure;
     412             :       ulong             fec_resolver_depth;
     413             :       ulong             slot_max;
     414             :       char              identity_key_path[ PATH_MAX ];
     415             :       ushort            shred_listen_port;
     416             :       ulong             max_shreds_per_block;
     417             :       ulong             bench_max_shreds_per_block; /* [development.bench], floors the chain's per-slot limit */
     418             :       ushort            expected_shred_version;
     419             :       ulong adtl_dests_retransmit_cnt;
     420             :       char  adtl_dests_retransmit[ FD_TOPO_ADTL_DESTS_MAX ][ FD_HOSTPORT_BUF_MAX ];
     421             :       ulong adtl_dests_leader_cnt;
     422             :       char  adtl_dests_leader[ FD_TOPO_ADTL_DESTS_MAX ][ FD_HOSTPORT_BUF_MAX ];
     423             :     } shred;
     424             : 
     425             :     struct {
     426             :       ulong disable_blockstore_from_slot;
     427             :     } store;
     428             : 
     429             :     struct {
     430             :       char  identity_key_path[ PATH_MAX ];
     431             :       int   failover_junk_fd; /* private startup pipe for the failover junk key, -1 without failover */
     432             :       int   failover_enabled;
     433             :       ulong authorized_voter_paths_cnt;
     434             :       char  authorized_voter_paths[ FD_KEYGUARD_AUTH_VOTERS_MAX ][ PATH_MAX ];
     435             :       struct {
     436             :         uchar tip_payment_program_addr[ 32 ];
     437             :         uchar tip_distribution_program_addr[ 32 ];
     438             :       } bundle;
     439             :     } sign;
     440             : 
     441             :     struct {
     442             :       uint   listen_addr;
     443             :       ushort listen_port;
     444             : 
     445             :       int    is_voting;
     446             : 
     447             :       char   cluster[ 32 ];
     448             :       char   identity_key_path[ PATH_MAX ];
     449             :       char   vote_key_path[ PATH_MAX ];
     450             :       char   accounts_database_path[ PATH_MAX ];
     451             :       char   gui_database_path[ PATH_MAX ];
     452             : 
     453             :       ulong  max_http_connections;
     454             :       ulong  max_websocket_connections;
     455             :       ulong  send_buffer_size_mb;
     456             :       ulong  db_size_gib;
     457             :       int    schedule_strategy;
     458             : 
     459             :       int websocket_compression;
     460             :       ulong tile_cnt;
     461             :       ulong max_live_slots;
     462             : 
     463             :       char   wfs_bank_hash[ FD_BASE58_ENCODED_32_SZ ];
     464             :       ulong  wfs_slot;
     465             :       ushort expected_shred_version;
     466             :       ulong  cache_size_gib;
     467             :       ulong  accdb_obj_id;
     468             :       ulong  max_txn_per_slot;
     469             :     } gui;
     470             : 
     471             :     struct {
     472             :       fd_ip6_addr_t listen_addr;
     473             :       ushort listen_port;
     474             : 
     475             :       ulong max_http_connections;
     476             :       ulong max_websocket_connections;
     477             :       ulong send_buffer_size_mb;
     478             : 
     479             :       ulong max_live_slots;
     480             :       ulong genesis_max_message_size;
     481             : 
     482             :       ulong accdb_obj_id;
     483             :       ulong accdb_epoch_fseq_obj_id;
     484             : 
     485             :       char identity_key_path[ PATH_MAX ];
     486             :       int  delay_startup;
     487             : 
     488             :       int    snapshot_server_enabled;
     489             :       char   snapshot_server_host[ FD_FQDN_BUF_MAX ];
     490             :       ushort snapshot_server_port;
     491             :     } rpc;
     492             : 
     493             :     struct {
     494             :       uint   prometheus_listen_addr;
     495             :       ushort prometheus_listen_port;
     496             :     } metric;
     497             : 
     498             :     struct {
     499             :       int is_voting;
     500             : 
     501             :       char accounts_path [ PATH_MAX ];
     502             :       char shreds_path   [ PATH_MAX ];
     503             :       char snapshots_path[ PATH_MAX ];
     504             :       char gui_path      [ PATH_MAX ];
     505             :       char log_path      [ PATH_MAX ];
     506             :     } diag;
     507             : 
     508             :     struct {
     509             :       ulong accdb_obj_id;
     510             :       ulong txncache_obj_id;
     511             : 
     512             :       char  identity_key_path[ PATH_MAX ];
     513             :       char  vote_account_path[ PATH_MAX ];
     514             : 
     515             :       fd_hash_t wait_for_supermajority_with_bank_hash;
     516             :       ulong     wait_for_supermajority_at_slot;
     517             :       ushort expected_shred_version;
     518             :       int    wait_for_vote_to_start_leader;
     519             : 
     520             :       ulong sched_depth;
     521             :       ulong max_live_slots;
     522             :       ulong genesis_max_message_size;
     523             :       ulong full_snapshot_interval_blocks;
     524             :       ulong incremental_snapshot_interval_blocks;
     525             : 
     526             :       /* not specified in TOML */
     527             : 
     528             :       long boot_timestamp_nanos;
     529             : 
     530             :       ulong enable_features_cnt;
     531             :       char  enable_features[ 16 ][ FD_BASE58_ENCODED_32_SZ ];
     532             : 
     533             :       char  genesis_path[ PATH_MAX ];
     534             : 
     535             :       ulong max_txn_per_slot;     /* config->limits */
     536             :       ulong max_shreds_per_block;
     537             : 
     538             :       ulong capture_start_slot;
     539             :       char  solcap_capture[ PATH_MAX ];
     540             :       char  dump_proto_dir[ PATH_MAX ];
     541             :       int   dump_block_to_pb;
     542             :       int   report_runtime_diffs;
     543             : 
     544             :       struct {
     545             :         int   enabled;
     546             :         uchar tip_payment_program_addr[ 32 ];
     547             :         uchar tip_distribution_program_addr[ 32 ];
     548             :         char  vote_account_path[ PATH_MAX ];
     549             :       } bundle;
     550             :     } replay;
     551             : 
     552             :     struct {
     553             :       ulong txncache_obj_id;
     554             :       ulong progcache_obj_id;
     555             :       ulong accdb_obj_id;
     556             :       ulong bpf_frames_obj_id;
     557             : 
     558             :       ulong max_live_slots;
     559             : 
     560             :       ulong capture_start_slot;
     561             :       char  solcap_capture[ PATH_MAX ];
     562             :       char  dump_proto_dir[ PATH_MAX ];
     563             :       char  dump_syscall_name_filter[ PATH_MAX ];
     564             :       char  dump_instr_program_id_filter[ FD_BASE58_ENCODED_32_SZ ];
     565             :       int   dump_instr_to_pb;
     566             :       int   dump_txn_to_pb;
     567             :       int   dump_txn_as_fixture;
     568             :       int   dump_syscall_to_pb;
     569             :       int   report_runtime_diffs;
     570             :     } execrp;
     571             : 
     572             :     struct {
     573             :       ushort send_to_port;
     574             :       uint   send_to_ip_addr;
     575             :       ulong  conn_cnt;
     576             :       int    no_quic;
     577             :     } benchs;
     578             : 
     579             :     struct {
     580             :       ushort rpc_port;
     581             :       uint   rpc_ip_addr;
     582             :       ulong  duration_s;
     583             :     } bencho;
     584             : 
     585             :     struct {
     586             :       ulong accounts_cnt;
     587             :       int   mode;
     588             :       float contending_fraction;
     589             :       float cu_price_spread;
     590             :     } benchg;
     591             : 
     592             :     struct {
     593             :       ushort  repair_client_listen_port;
     594             :       char    identity_key_path[ PATH_MAX ];
     595             :       ulong   slot_max;
     596             :       ulong   fec_max;
     597             :       ulong   max_shreds_per_block;
     598             :       int     allow_private_address;
     599             :       int     report_repair_requests;
     600             : 
     601             :       ulong   repair_sign_depth;
     602             :       ulong   repair_sign_cnt;
     603             :     } repair;
     604             : 
     605             :     struct {
     606             :       ushort repair_serve_listen_port;
     607             :       char   identity_key_path[ PATH_MAX ];
     608             :       ulong  ping_cache_entries;
     609             :       ulong  max_shreds_per_block;
     610             :       ulong  blockdb_max; /* 0 disables the block metadata db */
     611             :     } rserve;
     612             : 
     613             :     struct {
     614             :       uint fake_dst_ip;
     615             :     } pktgen;
     616             : 
     617             :     struct {
     618             :       char  ledger_format[ 16 ];
     619             :       char  ledger_path[ PATH_MAX ];
     620             :       ulong end_slot;
     621             :       ulong root_distance;
     622             :       long  boot_timestamp_nanos;
     623             :     } backtest;
     624             : 
     625             :     struct {
     626             :       char   identity_key_path[ PATH_MAX ];
     627             :       char   vote_history_path[ PATH_MAX ];
     628             :       uint   target_gid;
     629             :       uint   target_uid;
     630             :       ulong  authorized_voter_paths_cnt;
     631             :       ushort quic_client_listen_port;
     632             :       ushort quic_server_listen_port;
     633             :       uint   ip_addr;
     634             :       ulong  max_live_slots;
     635             :       ulong  wait_for_supermajority_at_slot;
     636             :       int    wait_for_supermajority_hash_is_zero;
     637             :       ushort expected_shred_version;
     638             :     } votor;
     639             : 
     640             :     struct {
     641             :       ulong accdb_obj_id;
     642             :       ulong max_live_slots;
     643             : 
     644             :       ulong rpc_epoch_obj_id;
     645             :       ulong resolv_epoch_obj_ids[ 16 ];
     646             :       ulong resolv_epoch_obj_cnt;
     647             :       ulong snapmk_epoch_obj_id;
     648             :       ulong snapzp_epoch_obj_ids[ 64 ];
     649             :       ulong snapzp_epoch_obj_cnt;
     650             :     } accdb;
     651             : 
     652             :     struct {
     653             :       ulong max_live_slots;
     654             :       ulong accdb_obj_id;
     655             :       ulong accdb_epoch_fseq_obj_id;
     656             :     } resolv;
     657             : 
     658             : 
     659             : #define FD_TOPO_SNAPSHOTS_GOSSIP_LIST_MAX      (32UL)
     660           0 : #define FD_TOPO_SNAPSHOTS_SERVERS_MAX          (16UL)
     661           0 : #define FD_TOPO_MAX_RESOLVED_ADDRS             ( 4UL)
     662           0 : #define FD_TOPO_SNAPSHOTS_SERVERS_MAX_RESOLVED (FD_TOPO_MAX_RESOLVED_ADDRS*FD_TOPO_SNAPSHOTS_SERVERS_MAX)
     663             : 
     664             :     struct fd_topo_tile_snapct {
     665             :       char  snapshots_path[ PATH_MAX ];
     666             : 
     667             :       ulong entrypoints_cnt;
     668             :       char  entrypoints[ FD_TOPO_GOSSIP_ENTRYPOINTS_MAX ][ FD_HOSTPORT_BUF_MAX ];
     669             : 
     670             :       struct {
     671             :         uint max_local_full_effective_age;
     672             :         uint max_local_incremental_age;
     673             : 
     674             :         struct {
     675             :           int         allow_any;
     676             :           ulong       allow_list_cnt;
     677             :           fd_pubkey_t allow_list[ FD_TOPO_SNAPSHOTS_GOSSIP_LIST_MAX ];
     678             :           ulong       block_list_cnt;
     679             :           fd_pubkey_t block_list[ FD_TOPO_SNAPSHOTS_GOSSIP_LIST_MAX ];
     680             :         } gossip;
     681             : 
     682             :         ulong         servers_cnt;
     683             :         char          servers[ FD_TOPO_SNAPSHOTS_SERVERS_MAX ][ FD_URL_MAX ];
     684             :       } sources;
     685             : 
     686             :       int    incremental_snapshots;
     687             :       uint   max_full_snapshots_to_keep;
     688             :       uint   max_incremental_snapshots_to_keep;
     689             :       uint   max_retry_abort;
     690             :       long   wait_for_peers_timeout_nanos;
     691             :       ulong  wfs_slot;
     692             :       int    wfs_hash_is_zero;
     693             :       ushort wfs_shred_version;
     694             :     } snapct;
     695             : 
     696             :     struct {
     697             :       char   snapshots_path[ PATH_MAX ];
     698             :       int    incremental_snapshots;
     699             :       uint   min_download_speed_mibs;
     700             :       ulong  wfs_slot;
     701             :       int    wfs_hash_is_zero;
     702             :       ushort wfs_shred_version;
     703             :     } snapld;
     704             : 
     705             :     struct {
     706             :       ulong     wait_for_supermajority_at_slot;
     707             :       fd_hash_t wait_for_supermajority_with_bank_hash;
     708             :       ushort    expected_shred_version;
     709             :       ulong     max_live_slots;
     710             :       ulong     accdb_obj_id;
     711             :       ulong     txncache_obj_id;
     712             :       ulong     banks_obj_id;
     713             :       ulong     shmem_obj_id; /* shared parallel snapin state */
     714             :       ulong     max_txn_per_slot;
     715             :     } snapin;
     716             : 
     717             :     struct {
     718             : 
     719             :       uint   bind_address;
     720             :       ushort bind_port;
     721             : 
     722             :       ushort expected_shred_version;
     723             :       ulong entrypoints_cnt;
     724             :       char  entrypoints[ FD_TOPO_GOSSIP_ENTRYPOINTS_MAX ][ FD_HOSTPORT_BUF_MAX ];
     725             :     } ipecho;
     726             : 
     727             :     struct {
     728             :       ulong max_live_slots;
     729             :       ulong txncache_obj_id;
     730             :       ulong progcache_obj_id;
     731             :       ulong accdb_obj_id;
     732             :       ulong bpf_frames_obj_id;
     733             :       int   report_runtime_diffs;
     734             :     } execle;
     735             : 
     736             :     struct {
     737             :       int validate_genesis_hash;
     738             :       int allow_download;
     739             : 
     740             :       ushort expected_shred_version;
     741             :       ulong entrypoints_cnt;
     742             :       char  entrypoints[ FD_TOPO_GOSSIP_ENTRYPOINTS_MAX ][ FD_HOSTPORT_BUF_MAX ];
     743             : 
     744             :       int has_expected_genesis_hash;
     745             :       uchar expected_genesis_hash[ 32UL ];
     746             : 
     747             :       char genesis_path[ PATH_MAX ];
     748             : 
     749             :       uint target_gid;
     750             :       uint target_uid;
     751             : 
     752             :       ulong max_live_slots;
     753             :       ulong accdb_obj_id;
     754             :       ulong max_message_size;
     755             :     } genesi;
     756             : 
     757             :     struct {
     758             :       ulong capture_start_slot;
     759             :       char  solcap_capture[ PATH_MAX ];
     760             :       int   recent_only;
     761             :       ulong recent_slots_per_file;
     762             :     } solcap;
     763             : 
     764             :     struct {
     765             :       ulong accdb_obj_id;
     766             :       ulong accdb_epoch_obj_id;
     767             :       ulong visited_set_obj_id;
     768             :       ulong banks_obj_id;
     769             :       ulong zp_fseq_id;
     770             :       ulong txncache_obj_id;
     771             :       ulong max_accounts;
     772             :       ulong max_live_slots;
     773             :       ulong max_txn_per_slot;
     774             :       uint  max_full_snapshots_to_keep;
     775             :       char  snapshots_path[ PATH_MAX ];
     776             :       uint  max_incremental_snapshots_to_keep;
     777             :     } snapmk;
     778             : 
     779             :     struct {
     780             :       ulong accdb_obj_id;
     781             :       ulong accdb_epoch_obj_id;
     782             :       ulong visited_set_obj_id;
     783             :       ulong zp_fseq_id;
     784             :       ulong max_live_slots;
     785             :       uint  snap_fd_cnt;
     786             :     } snapzp;
     787             : 
     788             :     struct {
     789             :       ulong accdb_obj_id;
     790             :     } snaprd;
     791             : 
     792             :     struct {
     793             :       ulong         snap_max;
     794             :       ulong         conn_max;
     795             :       uint          io_worker_cnt;
     796             :       ulong         idle_timeout_millis;
     797             :       ulong         send_timeout_millis;
     798             :       ulong         send_buffer_size_kib;
     799             :       fd_ip6_addr_t listen_addr;
     800             :       ushort        listen_port;
     801             :     } snapsv;
     802             :   };
     803             : };
     804             : 
     805             : typedef struct fd_topo_tile fd_topo_tile_t;
     806             : 
     807             : typedef struct {
     808             :   ulong id;
     809             :   char  name[ 14UL ];  /* object type */
     810             :   ulong wksp_id;
     811             : 
     812             :   /* Optional label for object */
     813             :   char  label[ 13UL ];  /* object label */
     814             :   ulong label_idx;      /* index of object for this label (ULONG_MAX if not labelled) */
     815             : 
     816             :   ulong offset;
     817             :   ulong footprint;
     818             : } fd_topo_obj_t;
     819             : 
     820             : /* An fd_topo_t represents the overall structure of a Firedancer
     821             :    configuration, describing all the workspaces, tiles, and links
     822             :    between them. */
     823             : struct fd_topo {
     824             :   char           app_name[ 256UL ];
     825             :   uchar          failover_junk[ 32 ]; /* public half of the junk key generated at boot for failover, zero without failover */
     826             :   uchar          props[ 32768UL ];
     827             : 
     828             :   ulong          sleep_obj_id;
     829             : 
     830             :   ulong          wksp_cnt;
     831             :   ulong          link_cnt;
     832             :   ulong          tile_cnt;
     833             :   ulong          obj_cnt;
     834             : 
     835             :   fd_topo_wksp_t workspaces[ FD_TOPO_MAX_WKSPS ];
     836             :   fd_topo_link_t links[ FD_TOPO_MAX_LINKS ];
     837             :   fd_topo_tile_t tiles[ FD_TOPO_MAX_TILES ];
     838             :   fd_topo_obj_t  objs[ FD_TOPO_MAX_OBJS ];
     839             : 
     840             :   ulong          blocklist_cores_cnt;
     841             :   ulong          blocklist_cores_cpu_idx[ FD_TILE_MAX ];
     842             : 
     843             :   ulong          max_page_size; /* 2^21 or 2^30 */
     844             :   ulong          gigantic_page_threshold; /* see [hugetlbfs.gigantic_page_threshold_mib]*/
     845             : 
     846             :   /* Rendered configuration documents for the boot telemetry event,
     847             :      filled by the app during topology construction. */
     848             :   ulong          resolved_config_json_len;
     849             :   char           resolved_config_json[ 262144UL ];
     850             :   ulong          user_config_json_len;
     851             :   char           user_config_json[ 131072UL ];
     852             : 
     853             :   ulong          layout_hash;
     854             : };
     855             : typedef struct fd_topo fd_topo_t;
     856             : 
     857             : typedef struct {
     858             :   char const * name;
     859             : 
     860             :   int          keep_host_networking;
     861             :   int          allow_connect;
     862             :   int          allow_renameat;
     863             :   ulong        rlimit_file_cnt;
     864             :   ulong        rlimit_address_space;
     865             :   ulong        rlimit_data;
     866             :   ulong        rlimit_nproc;
     867             :   int          for_tpool;
     868             : 
     869             :   ulong (*max_event_sz            )( fd_topo_tile_t const * tile );
     870             :   ulong (*populate_allowed_seccomp)( fd_topo_t const * topo, fd_topo_tile_t const * tile, ulong out_cnt, struct sock_filter * out );
     871             :   ulong (*populate_allowed_fds    )( fd_topo_t const * topo, fd_topo_tile_t const * tile, ulong out_fds_sz, int * out_fds );
     872             :   ulong (*scratch_align           )( void );
     873             :   ulong (*scratch_footprint       )( fd_topo_tile_t const * tile );
     874             :   ulong (*loose_footprint         )( fd_topo_tile_t const * tile );
     875             :   void  (*privileged_init         )( fd_topo_t const * topo, fd_topo_tile_t const * tile );
     876             :   void  (*unprivileged_init       )( fd_topo_t const * topo, fd_topo_tile_t const * tile );
     877             :   void  (*run                     )( fd_topo_t * topo, fd_topo_tile_t * tile );
     878             :   ulong (*rlimit_file_cnt_fn      )( fd_topo_t const * topo, fd_topo_tile_t const * tile );
     879             : } fd_topo_run_tile_t;
     880             : 
     881             : struct fd_topo_obj_callbacks {
     882             :   char const * name;
     883             :   ulong (* footprint )( fd_topo_t const * topo, fd_topo_obj_t const * obj );
     884             :   ulong (* align     )( fd_topo_t const * topo, fd_topo_obj_t const * obj );
     885             :   ulong (* loose     )( fd_topo_t const * topo, fd_topo_obj_t const * obj );
     886             :   void  (* new       )( fd_topo_t const * topo, fd_topo_obj_t const * obj );
     887             : };
     888             : 
     889             : typedef struct fd_topo_obj_callbacks fd_topo_obj_callbacks_t;
     890             : 
     891             : FD_PROTOTYPES_BEGIN
     892             : 
     893             : FD_FN_CONST static inline ulong
     894           0 : fd_topo_workspace_align( void ) {
     895             :   /* This needs to be the max( align ) of all the child members that
     896             :      could be aligned into this workspace, otherwise our footprint
     897             :      calculation will not be correct.  For now just set to 4096 but this
     898             :      should probably be calculated dynamically, or we should reduce
     899             :      those child aligns if we can. */
     900           0 :   return 4096UL;
     901           0 : }
     902             : 
     903             : void *
     904             : fd_topo_obj_laddr( fd_topo_t const * topo,
     905             :                    ulong             obj_id );
     906             : 
     907             : /* Returns a pointer in the local address space to the base address of
     908             :    the workspace out of which the given object was allocated. */
     909             : 
     910             : static inline void *
     911             : fd_topo_obj_wksp_base( fd_topo_t const * topo,
     912           0 :                        ulong             obj_id ) {
     913           0 :   FD_TEST( obj_id<FD_TOPO_MAX_OBJS );
     914           0 :   fd_topo_obj_t const * obj = &topo->objs[ obj_id ];
     915           0 :   FD_TEST( obj->id == obj_id );
     916           0 :   ulong const wksp_id = obj->wksp_id;
     917             : 
     918           0 :   FD_TEST( wksp_id<FD_TOPO_MAX_WKSPS );
     919           0 :   fd_topo_wksp_t const * wksp = &topo->workspaces[ wksp_id ];
     920           0 :   FD_TEST( wksp->id == wksp_id );
     921           0 :   return wksp->wksp;
     922           0 : }
     923             : 
     924             : FD_FN_PURE static inline ulong
     925             : fd_topo_tile_name_cnt( fd_topo_t const * topo,
     926           0 :                        char const *      name ) {
     927           0 :   ulong cnt = 0;
     928           0 :   for( ulong i=0; i<topo->tile_cnt; i++ ) {
     929           0 :     if( FD_UNLIKELY( !strcmp( topo->tiles[ i ].name, name ) ) ) cnt++;
     930           0 :   }
     931           0 :   return cnt;
     932           0 : }
     933             : 
     934             : /* Finds the workspace of a given name in the topology.  Returns
     935             :    ULONG_MAX if there is no such workspace.  There can be at most one
     936             :    workspace of a given name. */
     937             : 
     938             : FD_FN_PURE static inline ulong
     939             : fd_topo_find_wksp( fd_topo_t const * topo,
     940           0 :                    char const *      name ) {
     941           0 :   for( ulong i=0; i<topo->wksp_cnt; i++ ) {
     942           0 :     if( FD_UNLIKELY( !strcmp( topo->workspaces[ i ].name, name ) ) ) return i;
     943           0 :   }
     944           0 :   return ULONG_MAX;
     945           0 : }
     946             : 
     947             : /* Find the tile of a given name and kind_id in the topology, there will
     948             :    be at most one such tile, since kind_id is unique among the name.
     949             :    Returns ULONG_MAX if there is no such tile. */
     950             : 
     951             : FD_FN_PURE static inline ulong
     952             : fd_topo_find_tile( fd_topo_t const * topo,
     953             :                    char const *      name,
     954           0 :                    ulong             kind_id ) {
     955           0 :   for( ulong i=0; i<topo->tile_cnt; i++ ) {
     956           0 :     if( FD_UNLIKELY( !strcmp( topo->tiles[ i ].name, name ) ) && topo->tiles[ i ].kind_id == kind_id ) return i;
     957           0 :   }
     958           0 :   return ULONG_MAX;
     959           0 : }
     960             : 
     961             : /* Find the link of a given name and kind_id in the topology, there will
     962             :    be at most one such link, since kind_id is unique among the name.
     963             :    Returns ULONG_MAX if there is no such link. */
     964             : 
     965             : FD_FN_PURE static inline ulong
     966             : fd_topo_find_link( fd_topo_t const * topo,
     967             :                    char const *      name,
     968           0 :                    ulong             kind_id ) {
     969           0 :   for( ulong i=0; i<topo->link_cnt; i++ ) {
     970           0 :     if( FD_UNLIKELY( !strcmp( topo->links[ i ].name, name ) ) && topo->links[ i ].kind_id == kind_id ) return i;
     971           0 :   }
     972           0 :   return ULONG_MAX;
     973           0 : }
     974             : 
     975             : FD_FN_PURE static inline ulong
     976             : fd_topo_find_tile_in_link( fd_topo_t const *      topo,
     977             :                            fd_topo_tile_t const * tile,
     978             :                            char const *           name,
     979           0 :                            ulong                  kind_id ) {
     980           0 :   for( ulong i=0; i<tile->in_cnt; i++ ) {
     981           0 :     if( FD_UNLIKELY( !strcmp( topo->links[ tile->in_link_id[ i ] ].name, name ) )
     982           0 :         && topo->links[ tile->in_link_id[ i ] ].kind_id == kind_id ) return i;
     983           0 :   }
     984           0 :   return ULONG_MAX;
     985           0 : }
     986             : 
     987             : FD_FN_PURE static inline ulong
     988             : fd_topo_find_tile_out_link( fd_topo_t const *      topo,
     989             :                             fd_topo_tile_t const * tile,
     990             :                             char const *           name,
     991           0 :                             ulong                  kind_id ) {
     992           0 :   for( ulong i=0; i<tile->out_cnt; i++ ) {
     993           0 :     if( FD_UNLIKELY( !strcmp( topo->links[ tile->out_link_id[ i ] ].name, name ) )
     994           0 :         && topo->links[ tile->out_link_id[ i ] ].kind_id == kind_id ) return i;
     995           0 :   }
     996           0 :   return ULONG_MAX;
     997           0 : }
     998             : 
     999             : /* Find the id of the tile which is a producer for the given link.  If
    1000             :    no tile is a producer for the link, returns ULONG_MAX.  This should
    1001             :    not be possible for a well formed and validated topology.  */
    1002             : FD_FN_PURE static inline ulong
    1003             : fd_topo_find_link_producer( fd_topo_t const *      topo,
    1004           0 :                             fd_topo_link_t const * link ) {
    1005           0 :   for( ulong i=0; i<topo->tile_cnt; i++ ) {
    1006           0 :     fd_topo_tile_t const * tile = &topo->tiles[ i ];
    1007             : 
    1008           0 :     for( ulong j=0; j<tile->out_cnt; j++ ) {
    1009           0 :       if( FD_UNLIKELY( tile->out_link_id[ j ] == link->id ) ) return i;
    1010           0 :     }
    1011           0 :   }
    1012           0 :   return ULONG_MAX;
    1013           0 : }
    1014             : 
    1015             : /* Find the id of the tile which is a consumer of the given link.  If
    1016             :    no tile is a consumer of the link, returns ULONG_MAX. */
    1017             : FD_FN_PURE static inline ulong
    1018             : fd_topo_find_link_consumer( fd_topo_t const *      topo,
    1019           0 :                             fd_topo_link_t const * link ) {
    1020           0 :   for( ulong i=0; i<topo->tile_cnt; i++ ) {
    1021           0 :     fd_topo_tile_t const * tile = &topo->tiles[ i ];
    1022             : 
    1023           0 :     for( ulong j=0; j<tile->in_cnt; j++ ) {
    1024           0 :       if( FD_UNLIKELY( tile->in_link_id[ j ] == link->id ) ) return i;
    1025           0 :     }
    1026           0 :   }
    1027           0 :   return ULONG_MAX;
    1028           0 : }
    1029             : 
    1030             : /* Given a link, count the number of consumers of that link among all
    1031             :    the tiles in the topology. */
    1032             : FD_FN_PURE static inline ulong
    1033             : fd_topo_link_consumer_cnt( fd_topo_t const *      topo,
    1034           0 :                            fd_topo_link_t const * link ) {
    1035           0 :   ulong cnt = 0;
    1036           0 :   for( ulong i=0; i<topo->tile_cnt; i++ ) {
    1037           0 :     fd_topo_tile_t const * tile = &topo->tiles[ i ];
    1038           0 :     for( ulong j=0; j<tile->in_cnt; j++ ) {
    1039           0 :       if( FD_UNLIKELY( tile->in_link_id[ j ] == link->id ) ) cnt++;
    1040           0 :     }
    1041           0 :   }
    1042             : 
    1043           0 :   return cnt;
    1044           0 : }
    1045             : 
    1046             : /* Given a link, count the number of reliable consumers of that link
    1047             :    among all the tiles in the topology. */
    1048             : FD_FN_PURE static inline ulong
    1049             : fd_topo_link_reliable_consumer_cnt( fd_topo_t const *      topo,
    1050           0 :                                     fd_topo_link_t const * link ) {
    1051           0 :   ulong cnt = 0;
    1052           0 :   for( ulong i=0; i<topo->tile_cnt; i++ ) {
    1053           0 :     fd_topo_tile_t const * tile = &topo->tiles[ i ];
    1054           0 :     for( ulong j=0; j<tile->in_cnt; j++ ) {
    1055           0 :       if( FD_UNLIKELY( tile->in_link_id[ j ] == link->id && tile->in_link_reliable[ j ] ) ) cnt++;
    1056           0 :     }
    1057           0 :   }
    1058           0 : 
    1059           0 :   return cnt;
    1060           0 : }
    1061             : 
    1062             : FD_FN_PURE static inline ulong
    1063             : fd_topo_tile_consumer_cnt( fd_topo_t const *      topo,
    1064           0 :                            fd_topo_tile_t const * tile ) {
    1065           0 :   (void)topo;
    1066           0 :   return tile->out_cnt;
    1067           0 : }
    1068             : 
    1069             : FD_FN_PURE static inline ulong
    1070             : fd_topo_tile_reliable_consumer_cnt( fd_topo_t const *      topo,
    1071           0 :                                     fd_topo_tile_t const * tile ) {
    1072           0 :   ulong reliable_cons_cnt = 0UL;
    1073           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
    1074           0 :     fd_topo_tile_t const * consumer_tile = &topo->tiles[ i ];
    1075           0 :     for( ulong j=0UL; j<consumer_tile->in_cnt; j++ ) {
    1076           0 :       for( ulong k=0UL; k<tile->out_cnt; k++ ) {
    1077           0 :         if( FD_UNLIKELY( consumer_tile->in_link_id[ j ]==tile->out_link_id[ k ] && consumer_tile->in_link_reliable[ j ] ) ) {
    1078           0 :           reliable_cons_cnt++;
    1079           0 :         }
    1080           0 :       }
    1081           0 :     }
    1082           0 :   }
    1083           0 :   return reliable_cons_cnt;
    1084           0 : }
    1085             : 
    1086             : FD_FN_PURE static inline ulong
    1087             : fd_topo_tile_producer_cnt( fd_topo_t const *     topo,
    1088           0 :                            fd_topo_tile_t const * tile ) {
    1089           0 :   (void)topo;
    1090           0 :   ulong in_cnt = 0UL;
    1091           0 :   for( ulong i=0UL; i<tile->in_cnt; i++ ) {
    1092           0 :     if( FD_UNLIKELY( !tile->in_link_poll[ i ] ) ) continue;
    1093           0 :     in_cnt++;
    1094           0 :   }
    1095           0 :   return in_cnt;
    1096           0 : }
    1097             : 
    1098             : FD_FN_PURE FD_FN_UNUSED static ulong
    1099             : fd_topo_obj_cnt( fd_topo_t const * topo,
    1100             :                  char const *      obj_type,
    1101           0 :                  char const *      label ) {
    1102           0 :   ulong cnt = 0UL;
    1103           0 :   for( ulong i=0UL; i<topo->obj_cnt; i++ ) {
    1104           0 :     fd_topo_obj_t const * obj = &topo->objs[ i ];
    1105           0 :     if( strncmp( obj->name, obj_type, sizeof(obj->name) ) ) continue;
    1106           0 :     if( label &&
    1107           0 :         strncmp( obj->label, label, sizeof(obj->label) ) ) continue;
    1108           0 :     cnt++;
    1109           0 :   }
    1110           0 :   return cnt;
    1111           0 : }
    1112             : 
    1113             : FD_FN_PURE FD_FN_UNUSED static fd_topo_obj_t const *
    1114             : fd_topo_find_obj( fd_topo_t const * topo,
    1115             :                   char const *      obj_type,
    1116             :                   char const *      label,
    1117           0 :                   ulong             label_idx ) {
    1118           0 :   for( ulong i=0UL; i<topo->obj_cnt; i++ ) {
    1119           0 :     fd_topo_obj_t const * obj = &topo->objs[ i ];
    1120           0 :     if( strncmp( obj->name, obj_type, sizeof(obj->name) ) ) continue;
    1121           0 :     if( label &&
    1122           0 :         strncmp( obj->label, label, sizeof(obj->label) ) ) continue;
    1123           0 :     if( label_idx != ULONG_MAX && obj->label_idx != label_idx ) continue;
    1124           0 :     return obj;
    1125           0 :   }
    1126           0 :   return NULL;
    1127           0 : }
    1128             : 
    1129             : FD_FN_PURE FD_FN_UNUSED static fd_topo_obj_t const *
    1130             : fd_topo_find_tile_obj( fd_topo_t const *      topo,
    1131             :                        fd_topo_tile_t const * tile,
    1132           0 :                        char const *           obj_type ) {
    1133           0 :   for( ulong i=0UL; i<(tile->uses_obj_cnt); i++ ) {
    1134           0 :     fd_topo_obj_t const * obj = &topo->objs[ tile->uses_obj_id[ i ] ];
    1135           0 :     if( strncmp( obj->name, obj_type, sizeof(obj->name) ) ) continue;
    1136           0 :     return obj;
    1137           0 :   }
    1138           0 :   return NULL;
    1139           0 : }
    1140             : 
    1141             : /* Join (map into the process) all shared memory (huge/gigantic pages)
    1142             :    needed by the tile, in the given topology.  All memory associated
    1143             :    with the tile (aka. used by links that the tile either produces to or
    1144             :    consumes from, or used by the tile itself for its cnc) will be
    1145             :    attached (mapped into the process).
    1146             : 
    1147             :    This is needed to play nicely with the sandbox.  Once a process is
    1148             :    sandboxed we can no longer map any memory. */
    1149             : void
    1150             : fd_topo_join_tile_workspaces( fd_topo_t *      topo,
    1151             :                               fd_topo_tile_t * tile,
    1152             :                               int              core_dump_level );
    1153             : 
    1154             : /* Join (map into the process) the shared memory (huge/gigantic pages)
    1155             :    for the given workspace.  Mode is one of
    1156             :    FD_SHMEM_JOIN_MODE_READ_WRITE or FD_SHMEM_JOIN_MODE_READ_ONLY and
    1157             :    determines the prot argument that will be passed to mmap when mapping
    1158             :    the pages in (PROT_WRITE or PROT_READ respectively).
    1159             : 
    1160             :    Dump should be set to 1 if the workspace memory should be dumpable
    1161             :    when the process crashes, or 0 if not. */
    1162             : void
    1163             : fd_topo_join_workspace( fd_topo_t *      topo,
    1164             :                         fd_topo_wksp_t * wksp,
    1165             :                         int              mode,
    1166             :                         int              dump );
    1167             : 
    1168             : /* Join (map into the process) all shared memory (huge/gigantic pages)
    1169             :    needed by all tiles in the topology.  Mode is one of
    1170             :    FD_SHMEM_JOIN_MODE_READ_WRITE or FD_SHMEM_JOIN_MODE_READ_ONLY and
    1171             :    determines the prot argument that will be passed to mmap when
    1172             :    mapping the pages in (PROT_WRITE or PROT_READ respectively). */
    1173             : void
    1174             : fd_topo_join_workspaces( fd_topo_t *  topo,
    1175             :                          int          mode,
    1176             :                          int          core_dump_level );
    1177             : 
    1178             : /* Leave (unmap from the process) the shared memory needed for the
    1179             :    given workspace in the topology, if it was previously mapped.
    1180             : 
    1181             :    topo and wksp are assumed non-NULL.  It is OK if the workspace
    1182             :    has not been previously joined, in which case this is a no-op. */
    1183             : 
    1184             : void
    1185             : fd_topo_leave_workspace( fd_topo_t *      topo,
    1186             :                          fd_topo_wksp_t * wksp );
    1187             : 
    1188             : /* Leave (unmap from the process) all shared memory needed by all
    1189             :    tiles in the topology, if each of them was mapped.
    1190             : 
    1191             :    topo is assumed non-NULL.  Only workspaces which were previously
    1192             :    joined are unmapped. */
    1193             : 
    1194             : void
    1195             : fd_topo_leave_workspaces( fd_topo_t * topo );
    1196             : 
    1197             : /* Create the given workspace needed by the topology on the system.
    1198             :    This does not "join" the workspaces (map their memory into the
    1199             :    process), but only creates the .wksp file and formats it correctly
    1200             :    as a workspace.
    1201             : 
    1202             :    Returns 0 on success and -1 on failure, with errno set to the error.
    1203             :    The only reason for failure currently that will be returned is
    1204             :    ENOMEM, as other unexpected errors will cause the program to exit.
    1205             : 
    1206             :    If update_existing is 1, the workspace will not be created from
    1207             :    scratch but it will be assumed that it already exists from a prior
    1208             :    run and needs to be maybe resized and then have the header
    1209             :    structures reinitialized.  This can save a very expensive operation
    1210             :    of zeroing all of the workspace pages.  This is dangerous in
    1211             :    production because it can leave stray memory from prior runs around,
    1212             :    and should only be used in development environments. */
    1213             : 
    1214             : int
    1215             : fd_topo_create_workspace( fd_topo_t *      topo,
    1216             :                           fd_topo_wksp_t * wksp,
    1217             :                           int              update_existing );
    1218             : 
    1219             : /* Join the standard IPC objects needed by the topology of this particular
    1220             :    tile */
    1221             : 
    1222             : void
    1223             : fd_topo_fill_tile( fd_topo_t *      topo,
    1224             :                    fd_topo_tile_t * tile );
    1225             : 
    1226             : /* Same as fd_topo_fill_tile but fills in all the objects for a
    1227             :    particular workspace with the given mode. */
    1228             : void
    1229             : fd_topo_workspace_fill( fd_topo_t *      topo,
    1230             :                         fd_topo_wksp_t * wksp );
    1231             : 
    1232             : /* Apply a new function to every object that is resident in the given
    1233             :    workspace in the topology. */
    1234             : 
    1235             : void
    1236             : fd_topo_wksp_new( fd_topo_t const *          topo,
    1237             :                   fd_topo_wksp_t const *     wksp,
    1238             :                   fd_topo_obj_callbacks_t ** callbacks );
    1239             : 
    1240             : /* Same as fd_topo_fill_tile but fills in all tiles in the topology. */
    1241             : 
    1242             : void
    1243             : fd_topo_fill( fd_topo_t * topo );
    1244             : 
    1245             : /* fd_topo_tile_stack_join joins a huge page optimized stack for the
    1246             :    provided tile.  The stack is assumed to already exist at a known
    1247             :    path in the hugetlbfs mount. */
    1248             : 
    1249             : void *
    1250             : fd_topo_tile_stack_join( char const * app_name,
    1251             :                          char const * tile_name,
    1252             :                          ulong        tile_kind_id );
    1253             : 
    1254             : /* fd_topo_run_single_process runs all the tiles in a single process
    1255             :    (the calling process).  This spawns a thread for each tile, switches
    1256             :    that thread to the given UID and GID and then runs the tile in it.
    1257             :    Each thread will never exit, as tiles are expected to run forever.
    1258             :    An error is logged and the application will exit if a tile exits.
    1259             :    The function itself does return after spawning all the threads.
    1260             : 
    1261             :    The threads will not be sandboxed in any way, except switching to the
    1262             :    provided UID and GID, so they will share the same address space, and
    1263             :    not have any seccomp restrictions or use any Linux namespaces.  The
    1264             :    calling thread will also switch to the provided UID and GID before
    1265             :    it returns.
    1266             : 
    1267             :    This is useful for tooling and debugging, but is not how the main
    1268             :    production Firedancer process runs.  For production, each tile is run
    1269             :    in its own address space with a separate process and full security
    1270             :    sandbox. */
    1271             : 
    1272             : void
    1273             : fd_topo_run_single_process( fd_topo_t *       topo,
    1274             :                             uint              uid,
    1275             :                             uint              gid,
    1276             :                             fd_topo_run_tile_t (* tile_run )( fd_topo_tile_t const * tile ) );
    1277             : 
    1278             : /* fd_topo_run_tile runs the given tile directly within the current
    1279             :    process (and thread).  The function will never return, as tiles are
    1280             :    expected to run forever.  An error is logged and the application will
    1281             :    exit if the tile exits.
    1282             : 
    1283             :    The sandbox argument determines if the current process will be
    1284             :    sandboxed fully before starting the tile.  The thread will switch to
    1285             :    the UID and GID provided before starting the tile, even if the thread
    1286             :    is not being sandboxed.  Although POSIX specifies that all threads in
    1287             :    a process must share a UID and GID, this is not the case on Linux.
    1288             :    The thread will switch to the provided UID and GID without switching
    1289             :    the other threads in the process.
    1290             : 
    1291             :    If keep_controlling_terminal is set to 0, and the sandbox is enabled
    1292             :    the controlling terminal will be detached as an additional sandbox
    1293             :    measure, but you will not be able to send Ctrl+C or other signals
    1294             :    from the terminal.  See fd_sandbox.h for more information.
    1295             : 
    1296             :    The allow_fd argument is only used if sandbox is true, and is a file
    1297             :    descriptor which will be allowed to exist in the process.  Normally
    1298             :    the sandbox code rejects and aborts if there is an unexpected file
    1299             :    descriptor present on boot.  This is helpful to allow a parent
    1300             :    process to be notified on termination of the tile by waiting for a
    1301             :    pipe file descriptor to get closed.
    1302             : 
    1303             :    wait and debugger are both used in debugging.  If wait is non-NULL,
    1304             :    the runner will wait until the value pointed to by wait is non-zero
    1305             :    before launching the tile.  Likewise, if debugger is non-NULL, the
    1306             :    runner will wait until a debugger is attached before setting the
    1307             :    value pointed to by debugger to non-zero.  These are intended to be
    1308             :    used as a pair, where many tiles share a waiting reference, and then
    1309             :    one of the tiles (a tile you want to attach the debugger to) has the
    1310             :    same reference provided as the debugger, so all tiles will stop and
    1311             :    wait for the debugger to attach to it before proceeding. */
    1312             : 
    1313             : void
    1314             : fd_topo_run_tile( fd_topo_t *          topo,
    1315             :                   fd_topo_tile_t *     tile,
    1316             :                   int                  sandbox,
    1317             :                   int                  keep_controlling_terminal,
    1318             :                   int                  dumpable,
    1319             :                   uint                 uid,
    1320             :                   uint                 gid,
    1321             :                   int                  allow_fd,
    1322             :                   fd_topo_run_tile_t * tile_run );
    1323             : 
    1324             : /* This is for determining the value of RLIMIT_MLOCK that we need to
    1325             :    successfully run all tiles in separate processes.  The value returned
    1326             :    is the maximum amount of memory that will be locked with mlock() by
    1327             :    any individual process in the tree.  Specifically, if we have three
    1328             :    tile processes, and they each need to lock 5, 9, and 2 MiB of memory
    1329             :    respectively, RLIMIT_MLOCK needs to be 9 MiB to allow all three
    1330             :    process mlock() calls to succeed.
    1331             : 
    1332             :    Tiles lock memory in four ways.  Any workspace they are using, they
    1333             :    lock the entire workspace.  Then each tile uses huge pages for the
    1334             :    stack which are also locked, and finally some tiles use private
    1335             :    locked mmaps outside the workspace for storing key material.  Every
    1336             :    tile also locks the executable code.  The results here include all of
    1337             :    this memory together.
    1338             : 
    1339             :    The result is not necessarily the amount of memory used by the tile
    1340             :    process, although it will be quite close.  Tiles could potentially
    1341             :    allocate memory (eg, with brk) without needing to lock it, which
    1342             :    would not need to included, and some kernel memory that tiles cause
    1343             :    to be allocated (for example XSK buffers) is also not included.  The
    1344             :    actual amount of memory used will not be less than this value. */
    1345             : FD_FN_PURE ulong
    1346             : fd_topo_mlock_max_tile( fd_topo_t const * topo );
    1347             : 
    1348             : /* fd_topo_mlock_code locks the code, rodata and initialized data of
    1349             :    every loaded ELF object into DRAM, so tiles cannot stall on major
    1350             :    faults when the page cache is evicted under memory pressure. */
    1351             : 
    1352             : void
    1353             : fd_topo_mlock_code( void );
    1354             : 
    1355             : /* fd_topo_code_footprint returns the bytes that would be locked by
    1356             :    fd_topo_mlock_code, either the read-only segments (writable==0),
    1357             :    which are page cache shared by all tiles, or the writable segments
    1358             :    (writable==1), which are private to each tile process. */
    1359             : 
    1360             : ulong
    1361             : fd_topo_code_footprint( int writable );
    1362             : 
    1363             : /* Same as fd_topo_mlock_max_tile, but for loading the entire topology
    1364             :    into one process, rather than a separate process per tile.  This is
    1365             :    used, for example, by the configuration code when it creates all the
    1366             :    workspaces, or the monitor that maps the entire system into one
    1367             :    address space. */
    1368             : FD_FN_PURE ulong
    1369             : fd_topo_mlock( fd_topo_t const * topo );
    1370             : 
    1371             : /* This returns the number of gigantic pages needed by the topology on
    1372             :    the provided numa node.  It includes pages needed by the workspaces,
    1373             :    as well as additional allocations like huge pages for process stacks
    1374             :    and private key storage. */
    1375             : 
    1376             : FD_FN_PURE ulong
    1377             : fd_topo_gigantic_page_cnt( fd_topo_t const * topo,
    1378             :                            ulong             numa_idx );
    1379             : 
    1380             : /* This returns the number of huge pages in the application needed by
    1381             :    the topology on the provided numa node.  It includes pages needed by
    1382             :    things placed in the hugetlbfs (workspaces, process stacks).  If
    1383             :    include_anonymous is true, it also includes anonymous hugepages which
    1384             :    are needed but are not placed in the hugetlbfs. */
    1385             : 
    1386             : FD_FN_PURE ulong
    1387             : fd_topo_huge_page_cnt( fd_topo_t const * topo,
    1388             :                        ulong             numa_idx,
    1389             :                        int               include_anonymous );
    1390             : 
    1391             : /* Returns the number of normal (4 KiB) pages needed by the topology
    1392             :    for extra allocations like private key storage and XSK rings, plus
    1393             :    the locked code (read-only segments once, writable ones per tile). */
    1394             : 
    1395             : FD_FN_PURE ulong
    1396             : fd_topo_normal_page_cnt( fd_topo_t const * topo );
    1397             : 
    1398             : /* Prints a message describing the topology to an output stream.  If
    1399             :    stdout is true, will be written to stdout, otherwise will be written
    1400             :    as a NOTICE log message to the log file. */
    1401             : void
    1402             : fd_topo_print_log( int         stdout,
    1403             :                    fd_topo_t * topo );
    1404             : 
    1405             : /* fd_topo_print_json prints the same topology description as
    1406             :    fd_topo_print_log to stdout, as a JSON document. */
    1407             : void
    1408             : fd_topo_print_json( fd_topo_t * topo );
    1409             : 
    1410             : FD_PROTOTYPES_END
    1411             : 
    1412             : #endif /* HEADER_fd_src_disco_topo_fd_topo_h */

Generated by: LCOV version 1.14