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