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