Skip to content

Commit

Permalink
disco: refactor tiles into standard layout
Browse files Browse the repository at this point in the history
The tile code had been getting copy pasted and duplicated in interesting
ways that were starting to show their age.  This commit refactors all
of the tiles onto a standard infrastructure, the mux tile.  The mux tile
is used because it is the most general.

 * All tiles are rewritten to be a small wrapper around the mux tile.
   The mux tile gains some functionality, namely the ability to make
   callbacks to the user, to enable the tiles to change its behavior.
   This eliminates a large amount of boilerplate and makes it obvious
   in what ways each tile deviate from the standard.  Mux also gains
   the ability to filter fragments.

 * As part of this refactor, many of the deviations from the standard
   were removed because they were either no longer needed or were not
   correct. Some of these include,

    - Each flow control imlementation was subtly different, and these
      differences were dropped.  All flow control is now standard mux
      logic.  Same goes for deciding which (if any) producer to poll.
    - Redundant metrics written to the cnc diagnostic region by the
      QUIC tile are removed.
    - Some tiles republished ctl, tspub, and other fields, and some did
      not. All tiles now republish as appropriate.
    - The pack tile distributed to N consumers with N mcaches, rather
      than 1 like the mux tile.  It also repurposed flow control credits
      to be used as a "pack" credit, which wasn't being initialized
      correctly but also was unclear.
    - Various others.

 * The boundary between fdctl and frank has been removed, and the
   boundary betwen (what was) frank and disco has been clarified. The
   tiles in disco are an API, with fdctl as one of the callers.  The API
   boundary is that disco will not allocate any memory, and expects all
   objects needed to communicate with the rest of the system to be
   provided to it with no further configuration needed. Objects that are
   shared between multiple processes or need to be observed by a
   supervisor are created by, and then mapped into the tile processes.
   Objects only needed by an individual tile (for example, the tcache in
   dedup), are created in scratch space on the stack if possible, or if
   they are too large, in the tile's workspace. There are no other
   allocations.

 * The bounds checking on tile fragment readers has been improved (or
   implemented at all in some cases).

 * The QUIC tile has been refactored more deeply.  The raw UDP
   transaction handling is moved out to disco, and the context object
   for that logic is merged with the QUIC context object for simplicity.

 * The shared TPU workspace between tiles has been removed as a security
   issue, tiles are back to copying data between each stage of the TPU
   pipeline.

 * The TPU MTU was removed from the config file since it's always
   static.

 * The forwarding tile skeleton has been removed, since we have decided
   not to implement this functionality.

 * Moved the frank tile pieces into fdctl and removed all references to
   "frank" in the codebase. Frankendancer remains only in the README, to
   describe the current side-by-side model on main.

 * Removed disco from FFI, there's not really any reason anyone would
   need to call Firedancer tiles from Rust, and it just slowed down
   the build.

 * The dev1 command had broken at some point due to sandbox changes, and
   has been restored.

 * The `fd_tempo_tick_per_ns` calibration is moved to the `init` step
   of each tile, if they need to access fd_tempo_tick_per_ns, rather
   than being passed in via. fdctl.
  • Loading branch information
mmcgee-jump committed Sep 26, 2023
1 parent 743618d commit a2106f7
Show file tree
Hide file tree
Showing 57 changed files with 2,326 additions and 3,363 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/functional_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
- main
workflow_dispatch:
jobs:
frank-single-transaction:
single-transaction:
runs-on:
group: github-v1
env:
Expand All @@ -25,4 +25,4 @@ jobs:

- name: Run functional tests
run: |
./src/test/frank-single-transaction.sh
./src/test/single-transaction.sh
1 change: 0 additions & 1 deletion ffi/rust/firedancer-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ include = [
"staging",
"build.rs",
"wrapper_ballet.h",
"wrapper_disco.h",
"wrapper_tango.h",
"wrapper_util.h",
]
Expand Down
14 changes: 4 additions & 10 deletions ffi/rust/firedancer-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,11 @@ fn main() {
println!("cargo:rerun-if-changed=../../../src/ballet");
println!("cargo:rerun-if-changed=wrapper_tango.h");
println!("cargo:rerun-if-changed=../../../src/tango");
println!("cargo:rerun-if-changed=wrapper_disco.h");
println!("cargo:rerun-if-changed=../../../src/disco");

"../../../"
};

for lib in ["util", "ballet", "tango", "disco"] {
for lib in ["util", "ballet", "tango"] {
// Generate bindings to the header files
let mut builder = bindgen::Builder::default()
.wrap_static_fns(true)
Expand Down Expand Up @@ -179,12 +177,9 @@ fn main() {
.env("CC", "gcc") // Always use GCC for building FFI
.env("BASEDIR", out_dir.join("build"));

// No statics in disco yet so no extern wrapper file is produced
if lib != "disco" {
let key = format!("{}_STATIC_EXTERN_OBJECT", lib.to_uppercase());
let value = out_dir.join(&format!("gen_{}.c", lib));
command.env(key, value);
}
let key = format!("{}_STATIC_EXTERN_OBJECT", lib.to_uppercase());
let value = out_dir.join(&format!("gen_{}.c", lib));
command.env(key, value);

let output = command.output().unwrap_or_else(|_| {
panic!(
Expand All @@ -211,7 +206,6 @@ fn main() {
);
println!("cargo:rustc-link-lib=static=fd_util");
println!("cargo:rustc-link-lib=static=fd_tango");
println!("cargo:rustc-link-lib=static=fd_disco");
println!("cargo:rustc-link-lib=static=fd_ballet");
println!("cargo:rustc-link-lib=stdc++");
}
1 change: 0 additions & 1 deletion ffi/rust/firedancer-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ mod generated {

include!(concat!(env!("OUT_DIR"), "/bindings_util.rs"));
include!(concat!(env!("OUT_DIR"), "/bindings_ballet.rs"));
include!(concat!(env!("OUT_DIR"), "/bindings_disco.rs"));
include!(concat!(env!("OUT_DIR"), "/bindings_tango.rs"));
}

Expand Down
2 changes: 2 additions & 0 deletions ffi/rust/firedancer-sys/src/tango/dcache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pub use crate::generated::{
fd_dcache_app_laddr_const,
fd_dcache_app_sz,
fd_dcache_compact_chunk0,
fd_dcache_compact_wmark,
fd_dcache_compact_next,
fd_dcache_compact_is_safe,
fd_dcache_data_sz,
fd_dcache_delete,
Expand Down
1 change: 0 additions & 1 deletion ffi/rust/firedancer-sys/wrapper_disco.h

This file was deleted.

4 changes: 2 additions & 2 deletions src/app/fdctl/Local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ ifdef FD_HAS_DOUBLE

.PHONY: fdctl run monitor cargo

$(call add-objs,main1 config security utility run keygen ready monitor/monitor monitor/helper configure/configure configure/large_pages configure/sysctl configure/shmem configure/xdp configure/xdp_leftover configure/ethtool configure/workspace_leftover configure/workspace,fd_fdctl)
$(call make-bin-rust,fdctl,main,fd_fdctl fd_frank fd_disco fd_ballet fd_tango fd_util fd_quic solana_validator_fd)
$(call add-objs,main1 config security utility run/run run/tiles/dedup run/tiles/pack run/tiles/quic run/tiles/verify keygen ready monitor/monitor monitor/helper configure/configure configure/large_pages configure/sysctl configure/shmem configure/xdp configure/xdp_leftover configure/ethtool configure/workspace_leftover configure/workspace,fd_fdctl)
$(call make-bin-rust,fdctl,main,fd_fdctl fd_disco fd_ballet fd_tango fd_util fd_quic solana_validator_fd)
$(OBJDIR)/obj/app/fdctl/configure/xdp.o: src/tango/xdp/fd_xdp_redirect_prog.o
$(OBJDIR)/obj/app/fdctl/config.o: src/app/fdctl/config/default.toml

Expand Down
62 changes: 16 additions & 46 deletions src/app/fdctl/config.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "fdctl.h"

#include "../frank/fd_frank.h"
#include "run/run.h"

#include "../../util/net/fd_eth.h"

#include <stdio.h>
Expand All @@ -24,11 +25,10 @@ find_wksp( config_t * const config,
FD_LOG_ERR(( "no workspace with name `%s` found", name ));
}

/* partial frank_bank definition since the tile doesn't really exist */
static fd_frank_task_t frank_bank = {
/* partial bank definition since the tile doesn't really exist */
static fd_tile_config_t bank = {
.in_wksp = "pack_bank",
.out_wksp = "bank_shred",
.extra_wksp = NULL,
};

ulong
Expand All @@ -38,7 +38,7 @@ memlock_max_bytes( config_t * const config ) {
workspace_config_t * wksp = &config->shmem.workspaces[ j ];

#define TILE_MAX( tile ) do { \
ulong in_bytes = 0, out_bytes = 0, extra_bytes = 0; \
ulong in_bytes = 0, out_bytes = 0; \
if( FD_LIKELY( tile.in_wksp ) ) { \
workspace_config_t * in_wksp = find_wksp( config, tile.in_wksp ); \
in_bytes = in_wksp->num_pages * in_wksp->page_size; \
Expand All @@ -47,43 +47,33 @@ memlock_max_bytes( config_t * const config ) {
workspace_config_t * out_wksp = find_wksp( config, tile.out_wksp ); \
out_bytes = out_wksp->num_pages * out_wksp->page_size; \
} \
if( FD_LIKELY( tile.extra_wksp ) ) { \
workspace_config_t * extra_wksp = find_wksp( config, tile.extra_wksp ); \
extra_bytes = extra_wksp->num_pages * extra_wksp->page_size; \
} \
memlock_max_bytes = fd_ulong_max( memlock_max_bytes, \
wksp->page_size * wksp->num_pages + \
in_bytes + \
out_bytes + \
extra_bytes ); \
out_bytes ); \
} while(0)

switch ( wksp->kind ) {
case wksp_tpu_txn_data:
case wksp_quic_verify:
case wksp_verify_dedup:
case wksp_dedup_pack:
case wksp_pack_bank:
case wksp_pack_forward:
case wksp_bank_shred:
break;
case wksp_quic:
TILE_MAX( frank_quic );
TILE_MAX( quic );
break;
case wksp_verify:
TILE_MAX( frank_verify );
TILE_MAX( verify );
break;
case wksp_dedup:
TILE_MAX( frank_dedup );
TILE_MAX( dedup );
break;
case wksp_pack:
TILE_MAX( frank_pack );
TILE_MAX( pack );
break;
case wksp_bank:
TILE_MAX( frank_bank );
break;
case wksp_forward:
TILE_MAX( frank_forward );
TILE_MAX( bank );
break;
}
}
Expand Down Expand Up @@ -301,8 +291,6 @@ static void parse_key_value( config_t * config,

ENTRY_UINT ( ., tiles.bank, receive_buffer_size );

ENTRY_UINT ( ., tiles.forward, receive_buffer_size );

ENTRY_UINT ( ., tiles.dedup, signature_cache_size );
}

Expand Down Expand Up @@ -480,27 +468,21 @@ static void
init_workspaces( config_t * config ) {
ulong idx = 0;

config->shmem.workspaces[ idx ].kind = wksp_tpu_txn_data;
config->shmem.workspaces[ idx ].name = "tpu_txn_data";
config->shmem.workspaces[ idx ].page_size = FD_SHMEM_GIGANTIC_PAGE_SZ;
config->shmem.workspaces[ idx ].num_pages = 1;
idx++;

config->shmem.workspaces[ idx ].kind = wksp_quic_verify;
config->shmem.workspaces[ idx ].name = "quic_verify";
config->shmem.workspaces[ idx ].page_size = FD_SHMEM_HUGE_PAGE_SZ;
config->shmem.workspaces[ idx ].num_pages = 2;
config->shmem.workspaces[ idx ].page_size = FD_SHMEM_GIGANTIC_PAGE_SZ;
config->shmem.workspaces[ idx ].num_pages = 1;
idx++;

config->shmem.workspaces[ idx ].kind = wksp_verify_dedup;
config->shmem.workspaces[ idx ].name = "verify_dedup";
config->shmem.workspaces[ idx ].page_size = FD_SHMEM_HUGE_PAGE_SZ;
config->shmem.workspaces[ idx ].num_pages = 2;
config->shmem.workspaces[ idx ].page_size = FD_SHMEM_GIGANTIC_PAGE_SZ;
config->shmem.workspaces[ idx ].num_pages = 1;
idx++;

config->shmem.workspaces[ idx ].kind = wksp_dedup_pack;
config->shmem.workspaces[ idx ].name = "dedup_pack";
config->shmem.workspaces[ idx ].page_size = FD_SHMEM_HUGE_PAGE_SZ;
config->shmem.workspaces[ idx ].page_size = FD_SHMEM_GIGANTIC_PAGE_SZ;
config->shmem.workspaces[ idx ].num_pages = 1;
idx++;

Expand All @@ -510,12 +492,6 @@ init_workspaces( config_t * config ) {
config->shmem.workspaces[ idx ].num_pages = 1;
idx++;

config->shmem.workspaces[ idx ].kind = wksp_pack_forward;
config->shmem.workspaces[ idx ].name = "pack_forward";
config->shmem.workspaces[ idx ].page_size = FD_SHMEM_GIGANTIC_PAGE_SZ;
config->shmem.workspaces[ idx ].num_pages = 1;
idx++;

config->shmem.workspaces[ idx ].kind = wksp_bank_shred;
config->shmem.workspaces[ idx ].name = "bank_shred";
config->shmem.workspaces[ idx ].page_size = FD_SHMEM_GIGANTIC_PAGE_SZ;
Expand Down Expand Up @@ -552,12 +528,6 @@ init_workspaces( config_t * config ) {
config->shmem.workspaces[ idx ].num_pages = 1;
idx++;

config->shmem.workspaces[ idx ].kind = wksp_forward;
config->shmem.workspaces[ idx ].name = "forward";
config->shmem.workspaces[ idx ].page_size = FD_SHMEM_GIGANTIC_PAGE_SZ;
config->shmem.workspaces[ idx ].num_pages = 1;
idx++;

for( ulong i=0; i<config->layout.bank_tile_count; i++ ) {
config->shmem.workspaces[ idx ].kind = wksp_bank;
config->shmem.workspaces[ idx ].name = "bank";
Expand Down
7 changes: 0 additions & 7 deletions src/app/fdctl/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,16 @@

typedef struct {
enum {
wksp_tpu_txn_data,
wksp_quic_verify,
wksp_verify_dedup,
wksp_dedup_pack,
wksp_pack_bank,
wksp_pack_forward,
wksp_bank_shred,
wksp_quic,
wksp_verify,
wksp_dedup,
wksp_pack,
wksp_bank,
wksp_forward,
} kind;
char * name;
ulong kind_idx;
Expand Down Expand Up @@ -163,10 +160,6 @@ typedef struct {
uint receive_buffer_size;
} bank;

struct {
uint receive_buffer_size;
} forward;

struct {
uint signature_cache_size;
} dedup;
Expand Down
14 changes: 1 addition & 13 deletions src/app/fdctl/config/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ dynamic_port_range = "8000-10000"
#
# It is suggested to use all available CPU cores for Firedancer, so that the
# Solana network can run as fast as possible.
affinity = "0-14"
affinity = "0-13"

# How many verify tiles to run. Currently this also configures the number of
# QUIC tiles to run. QUIC and verify tiles are connected 1:1.
Expand Down Expand Up @@ -480,12 +480,6 @@ dynamic_port_range = "8000-10000"
# dropped. TODO: ... Should this really be configurable?
receive_buffer_size = 16384

# The maximum size of a message from a QUIC tile to a verify tile.
#
# TODO: This should be removed. Not configuration, should be transaction
# MTU.
mtu = 4804

# The pack tile takes incoming transactions that have been verified by the
# verify tile and attempts to order them in an optimal way to generate the
# most fees per compute resource used to execute them.
Expand Down Expand Up @@ -520,12 +514,6 @@ dynamic_port_range = "8000-10000"
[tiles.bank]
receive_buffer_size = 128

# The forward tile sends unprocessed transactions.
# Forwarding only occures when the current instance is the leader and it
# is unable to process all transactions in its leader slot.
[tiles.forward]
receive_buffer_size = 128

# All transactions entering into the validator are deduplicated after their
# signature is verified, to ensure the same transaction is not repeated
# multiple times.
Expand Down
3 changes: 0 additions & 3 deletions src/app/fdctl/configure/large_pages.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,17 @@ expected_pages( config_t * const config, uint out[2] ) {

for( ulong i=0; i<config->shmem.workspaces_cnt; i++ ) {
switch( config->shmem.workspaces[ i ].kind ) {
case wksp_tpu_txn_data:
case wksp_quic_verify:
case wksp_verify_dedup:
case wksp_dedup_pack:
case wksp_pack_bank:
case wksp_pack_forward:
case wksp_bank_shred:
break;
case wksp_quic:
case wksp_verify:
case wksp_dedup:
case wksp_pack:
case wksp_bank:
case wksp_forward:
num_tiles++;
break;
}
Expand Down
Loading

0 comments on commit a2106f7

Please sign in to comment.