diff --git a/book/api/metrics-generated.md b/book/api/metrics-generated.md index 451830dd95..212fec3e69 100644 --- a/book/api/metrics-generated.md +++ b/book/api/metrics-generated.md @@ -49,7 +49,8 @@ | Metric | Type | Description | |--------|------|-------------| -| net_​rx_​pkt_​cnt | counter | Packet receive count. | +| net_​rx_​pkt_​cnt
{pkt_​kind="ip4_​udp"} | counter | Packet receive count. (IPv4 UDP packet (no options)) | +| net_​rx_​pkt_​cnt
{pkt_​kind="ip4_​opt_​udp"} | counter | Packet receive count. (IPv4 UDP packet (with options)) | | net_​rx_​bytes_​total | counter | Total number of bytes received (including Ethernet header). | | net_​rx_​undersz_​cnt | counter | Number of incoming packets dropped due to being too small. | | net_​rx_​fill_​blocked_​cnt | counter | Number of incoming packets dropped due to fill ring being full. | diff --git a/src/app/fdctl/topology.c b/src/app/fdctl/topology.c index dfaaeaba28..ef0bf74971 100644 --- a/src/app/fdctl/topology.c +++ b/src/app/fdctl/topology.c @@ -380,14 +380,17 @@ fd_topo_initialize( config_t * config ) { FOR(net_tile_cnt) fd_topos_net_tile_finish( topo, i ); + fd_topo_net_rx_t rx_rules = {0}; + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_SHRED, "net_shred", config->tiles.shred.shred_listen_port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_TPU_QUIC, "net_quic" , config->tiles.quic.quic_transaction_listen_port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_TPU_UDP, "net_quic" , config->tiles.quic.regular_transaction_listen_port ); + for( ulong i=0UL; itile_cnt; i++ ) { fd_topo_tile_t * tile = &topo->tiles[ i ]; if( FD_UNLIKELY( !strcmp( tile->name, "net" ) || !strcmp( tile->name, "sock" ) ) ) { - tile->net.shred_listen_port = config->tiles.shred.shred_listen_port; - tile->net.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port; - tile->net.legacy_transaction_listen_port = config->tiles.quic.regular_transaction_listen_port; + tile->net.rx_rules = rx_rules; } else if( FD_UNLIKELY( !strcmp( tile->name, "netlnk" ) ) ) { diff --git a/src/app/firedancer-dev/commands/backtest.c b/src/app/firedancer-dev/commands/backtest.c index 18fe8f56ac..10f4e90306 100644 --- a/src/app/firedancer-dev/commands/backtest.c +++ b/src/app/firedancer-dev/commands/backtest.c @@ -323,7 +323,7 @@ backtest_topo( config_t * config ) { for( ulong i=0UL; itile_cnt; i++ ) { fd_topo_tile_t * tile = &topo->tiles[ i ]; - if( !fd_topo_configure_tile( tile, config ) ) { + if( !fd_topo_configure_tile( tile, config, NULL ) ) { FD_LOG_ERR(( "unknown tile name %lu `%s`", i, tile->name )); } diff --git a/src/app/firedancer-dev/commands/gossip.c b/src/app/firedancer-dev/commands/gossip.c index 20c4470e35..3b3b4848d6 100644 --- a/src/app/firedancer-dev/commands/gossip.c +++ b/src/app/firedancer-dev/commands/gossip.c @@ -42,7 +42,7 @@ gossip_topo( config_t * config ) { if( net_tile_id==ULONG_MAX ) net_tile_id = fd_topo_find_tile( topo, "sock", 0UL ); if( FD_UNLIKELY( net_tile_id==ULONG_MAX ) ) FD_LOG_ERR(( "net tile not found" )); fd_topo_tile_t * net_tile = &topo->tiles[ net_tile_id ]; - net_tile->net.gossip_listen_port = config->gossip.port; + fd_topo_net_rx_rule_push( &net_tile->net.rx_rules, DST_PROTO_GOSSIP, "net_gossip", config->gossip.port ); fd_topob_wksp( topo, "gossip" ); fd_topo_tile_t * gossip_tile = fd_topob_tile( topo, "gossip", "gossip", "metric_in", 0UL, 0, 0 ); diff --git a/src/app/firedancer-dev/commands/repair.c b/src/app/firedancer-dev/commands/repair.c index b6fa38d361..c80edfc2b7 100644 --- a/src/app/firedancer-dev/commands/repair.c +++ b/src/app/firedancer-dev/commands/repair.c @@ -58,9 +58,8 @@ static void repair_topo( config_t * config ) { resolve_gossip_entrypoints( config ); - ulong net_tile_cnt = config->layout.net_tile_count; - ulong shred_tile_cnt = config->layout.shred_tile_count; - ulong quic_tile_cnt = config->layout.quic_tile_count; + ulong net_tile_cnt = config->layout.net_tile_count; + ulong shred_tile_cnt = config->layout.shred_tile_count; fd_topo_t * topo = { fd_topob_new( &config->topo, config->name ) }; topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size ); @@ -71,7 +70,6 @@ repair_topo( config_t * config ) { fd_topob_wksp( topo, "net_shred" ); fd_topob_wksp( topo, "net_gossip" ); fd_topob_wksp( topo, "net_repair" ); - fd_topob_wksp( topo, "net_quic" ); fd_topob_wksp( topo, "shred_repair" ); fd_topob_wksp( topo, "stake_out" ); @@ -93,8 +91,6 @@ repair_topo( config_t * config ) { fd_topob_wksp( topo, "sign_repair" ); fd_topob_wksp( topo, "repair_repla" ); - fd_topob_wksp( topo, "gossip_send" ); - fd_topob_wksp( topo, "send_txns" ); fd_topob_wksp( topo, "shred" ); fd_topob_wksp( topo, "sign" ); @@ -111,7 +107,6 @@ repair_topo( config_t * config ) { ulong pending_fec_shreds_depth = fd_ulong_min( fd_ulong_pow2_up( config->tiles.shred.max_pending_shred_sets * FD_REEDSOL_DATA_SHREDS_MAX ), USHORT_MAX + 1 /* dcache max */ ); /* topo, link_name, wksp_name, depth, mtu, burst */ - FOR(quic_tile_cnt) fd_topob_link( topo, "quic_net", "net_quic", config->net.ingress_buffer_size, FD_NET_MTU, 1UL ); FOR(shred_tile_cnt) fd_topob_link( topo, "shred_net", "net_shred", config->net.ingress_buffer_size, FD_NET_MTU, 1UL ); /**/ fd_topob_link( topo, "stake_out", "stake_out", 128UL, 40UL + 40200UL * 40UL, 1UL ); @@ -127,7 +122,6 @@ repair_topo( config_t * config ) { /**/ fd_topob_link( topo, "crds_shred", "crds_shred", 128UL, 8UL + 40200UL * 38UL, 1UL ); /**/ fd_topob_link( topo, "gossip_repai", "gossip_repai", 128UL, 40200UL * 38UL, 1UL ); - /**/ fd_topob_link( topo, "gossip_send", "gossip_send", 128UL, 40200UL * 38UL, 1UL ); /**/ fd_topob_link( topo, "gossip_net", "net_gossip", config->net.ingress_buffer_size, FD_NET_MTU, 1UL ); @@ -140,8 +134,6 @@ repair_topo( config_t * config ) { /**/ fd_topob_link( topo, "repair_repla", "repair_repla", 65536UL, sizeof(fd_reasm_fec_t), 1UL ); /**/ fd_topob_link( topo, "poh_shred", "poh_shred", 16384UL, USHORT_MAX, 1UL ); - /**/ fd_topob_link( topo, "send_txns", "send_txns", 128UL, FD_TXN_MTU, 1UL ); - FD_TEST( sizeof(fd_snapshot_manifest_t)<=(5UL*(1UL<<30UL)) ); /**/ fd_topob_link( topo, "snap_out", "snap_out", 2UL, 5UL*(1UL<<30UL), 1UL ); @@ -176,7 +168,6 @@ repair_topo( config_t * config ) { FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_gossip", i, config->net.ingress_buffer_size ); FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_repair", i, config->net.ingress_buffer_size ); - FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_quic", i, config->net.ingress_buffer_size ); FOR(net_tile_cnt) fd_topos_net_rx_link( topo, "net_shred", i, config->net.ingress_buffer_size ); /* topo, tile_name, tile_wksp, metrics_wksp, cpu_idx, is_agave, uses_keyswitch */ @@ -254,10 +245,6 @@ repair_topo( config_t * config ) { /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */ for( ulong j=0UL; jtiles.shred.shred_listen_port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_GOSSIP, "net_gossip", config->gossip.port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_REPAIR, "net_repair", config->tiles.repair.repair_intake_listen_port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_REPAIR, "net_repair", config->tiles.repair.repair_serve_listen_port ); + for( ulong i=0UL; itile_cnt; i++ ) { fd_topo_tile_t * tile = &topo->tiles[ i ]; - if( !fd_topo_configure_tile( tile, config ) ) { + if( !fd_topo_configure_tile( tile, config, &rx_rules ) ) { FD_LOG_ERR(( "unknown tile name %lu `%s`", i, tile->name )); } } diff --git a/src/app/firedancer-dev/commands/sim.c b/src/app/firedancer-dev/commands/sim.c index 2cd19d2196..52cc0b6289 100644 --- a/src/app/firedancer-dev/commands/sim.c +++ b/src/app/firedancer-dev/commands/sim.c @@ -174,7 +174,7 @@ sim_topo( config_t * config ) { } else { FD_LOG_NOTICE(( "Found archive file from config: %s", tile->archiver.rocksdb_path )); } - } else if( !fd_topo_configure_tile( tile, config ) ) { + } else if( !fd_topo_configure_tile( tile, config, NULL ) ) { FD_LOG_ERR(( "unknown tile name %lu `%s`", i, tile->name )); } diff --git a/src/app/firedancer-dev/commands/snapshot_load.c b/src/app/firedancer-dev/commands/snapshot_load.c index 165025db22..b6c7cdb47b 100644 --- a/src/app/firedancer-dev/commands/snapshot_load.c +++ b/src/app/firedancer-dev/commands/snapshot_load.c @@ -102,7 +102,7 @@ snapshot_load_topo( config_t * config, for( ulong i=0UL; itile_cnt; i++ ) { fd_topo_tile_t * tile = &topo->tiles[ i ]; - if( !fd_topo_configure_tile( tile, config ) ) { + if( !fd_topo_configure_tile( tile, config, NULL ) ) { FD_LOG_ERR(( "unknown tile name %lu `%s`", i, tile->name )); } } diff --git a/src/app/firedancer/topology.c b/src/app/firedancer/topology.c index ffddd7ac1b..dc954fc143 100644 --- a/src/app/firedancer/topology.c +++ b/src/app/firedancer/topology.c @@ -825,9 +825,18 @@ fd_topo_initialize( config_t * config ) { FOR(net_tile_cnt) fd_topos_net_tile_finish( topo, i ); + fd_topo_net_rx_t rx_rules = {0}; + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_TPU_QUIC, "net_quic", config->tiles.quic.quic_transaction_listen_port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_TPU_QUIC, "net_quic", config->tiles.quic.quic_transaction_listen_port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_SHRED, "net_shred", config->tiles.shred.shred_listen_port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_GOSSIP, "net_gossip", config->gossip.port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_REPAIR, "net_repair", config->tiles.repair.repair_intake_listen_port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_REPAIR, "net_repair", config->tiles.repair.repair_serve_listen_port ); + fd_topo_net_rx_rule_push( &rx_rules, DST_PROTO_SEND, "net_send", config->tiles.send.send_src_port ); + for( ulong i=0UL; itile_cnt; i++ ) { fd_topo_tile_t * tile = &topo->tiles[ i ]; - if( !fd_topo_configure_tile( tile, config ) ) { + if( !fd_topo_configure_tile( tile, config, &rx_rules ) ) { FD_LOG_ERR(( "unknown tile name %lu `%s`", i, tile->name )); } } @@ -858,17 +867,12 @@ fd_topo_initialize( config_t * config ) { } int -fd_topo_configure_tile( fd_topo_tile_t * tile, - fd_config_t * config ) { - if( FD_UNLIKELY( !strcmp( tile->name, "net" ) || !strcmp( tile->name, "sock" ) ) ) { - - tile->net.shred_listen_port = config->tiles.shred.shred_listen_port; - tile->net.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port; - tile->net.legacy_transaction_listen_port = config->tiles.quic.regular_transaction_listen_port; - tile->net.gossip_listen_port = config->gossip.port; - tile->net.repair_intake_listen_port = config->tiles.repair.repair_intake_listen_port; - tile->net.repair_serve_listen_port = config->tiles.repair.repair_serve_listen_port; - tile->net.send_src_port = config->tiles.send.send_src_port; +fd_topo_configure_tile( fd_topo_tile_t * tile, + fd_config_t * config, + fd_topo_net_rx_t const * rx_rules ) { + if( FD_UNLIKELY( rx_rules && (!strcmp( tile->name, "net" ) || !strcmp( tile->name, "sock" )) ) ) { + + tile->net.rx_rules = *rx_rules; } else if( FD_UNLIKELY( !strcmp( tile->name, "netlnk" ) ) ) { diff --git a/src/app/firedancer/topology.h b/src/app/firedancer/topology.h index 0aaf044353..4211d81083 100644 --- a/src/app/firedancer/topology.h +++ b/src/app/firedancer/topology.h @@ -49,8 +49,9 @@ setup_topo_txncache( fd_topo_t * topo, ulong max_txn_per_slot ); int -fd_topo_configure_tile( fd_topo_tile_t * tile, - fd_config_t * config ); +fd_topo_configure_tile( fd_topo_tile_t * tile, + fd_config_t * config, + fd_topo_net_rx_t const * rx_rules ); FD_PROTOTYPES_END diff --git a/src/app/shared/commands/get_identity.c b/src/app/shared/commands/get_identity.c index e89a6aa420..88df408b73 100644 --- a/src/app/shared/commands/get_identity.c +++ b/src/app/shared/commands/get_identity.c @@ -30,7 +30,7 @@ get_identity_cmd_fn( args_t * args FD_PARAM_UNUSED, fd_topo_join_workspace( &config->topo, &config->topo.workspaces[ shred_wksp_id ], FD_SHMEM_JOIN_MODE_READ_ONLY ); /* Cast to shred context structure */ - fd_shred_ctx_t const * shred_ctx = fd_topo_obj_laddr( &config->topo, shred_tile->tile_obj_id ); + fd_shred_ctx_hdr_t const * shred_ctx = fd_topo_obj_laddr( &config->topo, shred_tile->tile_obj_id ); if( FD_UNLIKELY( !shred_ctx ) ) { fd_topo_leave_workspaces( &config->topo ); FD_LOG_ERR(( "Failed to access shred tile object" )); diff --git a/src/app/shared_dev/commands/pktgen/pktgen.c b/src/app/shared_dev/commands/pktgen/pktgen.c index 347a9a5fd2..35b4d6d546 100644 --- a/src/app/shared_dev/commands/pktgen/pktgen.c +++ b/src/app/shared_dev/commands/pktgen/pktgen.c @@ -197,7 +197,7 @@ pktgen_cmd_fn( args_t * args FD_PARAM_UNUSED, fd_topo_tile_t * metric_tile = &topo->tiles[ fd_topo_find_tile( topo, "metric", 0UL ) ]; ushort const listen_port = 9000; - net_tile->net.legacy_transaction_listen_port = listen_port; + fd_topo_net_rx_rule_push( &net_tile->net.rx_rules, DST_PROTO_TPU_UDP, "net_quic", listen_port ); if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.metric.prometheus_listen_address, &metric_tile->metric.prometheus_listen_addr ) ) ) FD_LOG_ERR(( "failed to parse prometheus listen address `%s`", config->tiles.metric.prometheus_listen_address )); diff --git a/src/app/shared_dev/commands/udpecho/udpecho.c b/src/app/shared_dev/commands/udpecho/udpecho.c index f8a74d06eb..9e31fc0dfe 100644 --- a/src/app/shared_dev/commands/udpecho/udpecho.c +++ b/src/app/shared_dev/commands/udpecho/udpecho.c @@ -88,7 +88,7 @@ udpecho_cmd_fn( args_t * args, fd_topo_tile_t * net_tile = &topo->tiles[ fd_topo_find_tile( topo, "net", 0UL ) ]; fd_topo_tile_t * metric_tile = &topo->tiles[ fd_topo_find_tile( topo, "metric", 0UL ) ]; - net_tile->net.legacy_transaction_listen_port = args->udpecho.listen_port; + fd_topo_net_rx_rule_push( &net_tile->net.rx_rules, DST_PROTO_TPU_UDP, "net_quic", args->udpecho.listen_port ); if( FD_UNLIKELY( !fd_cstr_to_ip4_addr( config->tiles.metric.prometheus_listen_address, &metric_tile->metric.prometheus_listen_addr ) ) ) FD_LOG_ERR(( "failed to parse prometheus listen address `%s`", config->tiles.metric.prometheus_listen_address )); diff --git a/src/disco/metrics/generated/fd_metrics_enums.h b/src/disco/metrics/generated/fd_metrics_enums.h index 7f8aeb5236..b59ea62969 100644 --- a/src/disco/metrics/generated/fd_metrics_enums.h +++ b/src/disco/metrics/generated/fd_metrics_enums.h @@ -19,6 +19,13 @@ #define FD_METRICS_ENUM_TILE_REGIME_V_PROCESSING_POSTFRAG_IDX 7 #define FD_METRICS_ENUM_TILE_REGIME_V_PROCESSING_POSTFRAG_NAME "processing_postfrag" +#define FD_METRICS_ENUM_PKT_KIND_NAME "pkt_kind" +#define FD_METRICS_ENUM_PKT_KIND_CNT (2UL) +#define FD_METRICS_ENUM_PKT_KIND_V_IP4_UDP_IDX 0 +#define FD_METRICS_ENUM_PKT_KIND_V_IP4_UDP_NAME "ip4_udp" +#define FD_METRICS_ENUM_PKT_KIND_V_IP4_OPT_UDP_IDX 1 +#define FD_METRICS_ENUM_PKT_KIND_V_IP4_OPT_UDP_NAME "ip4_opt_udp" + #define FD_METRICS_ENUM_SOCK_ERR_NAME "sock_err" #define FD_METRICS_ENUM_SOCK_ERR_CNT (6UL) #define FD_METRICS_ENUM_SOCK_ERR_V_NO_ERROR_IDX 0 diff --git a/src/disco/metrics/generated/fd_metrics_net.c b/src/disco/metrics/generated/fd_metrics_net.c index 9a1115d3d0..8b6f45d385 100644 --- a/src/disco/metrics/generated/fd_metrics_net.c +++ b/src/disco/metrics/generated/fd_metrics_net.c @@ -2,7 +2,8 @@ #include "fd_metrics_net.h" const fd_metrics_meta_t FD_METRICS_NET[FD_METRICS_NET_TOTAL] = { - DECLARE_METRIC( NET_RX_PKT_CNT, COUNTER ), + DECLARE_METRIC_ENUM( NET_RX_PKT_CNT, COUNTER, PKT_KIND, IP4_UDP ), + DECLARE_METRIC_ENUM( NET_RX_PKT_CNT, COUNTER, PKT_KIND, IP4_OPT_UDP ), DECLARE_METRIC( NET_RX_BYTES_TOTAL, COUNTER ), DECLARE_METRIC( NET_RX_UNDERSZ_CNT, COUNTER ), DECLARE_METRIC( NET_RX_FILL_BLOCKED_CNT, COUNTER ), diff --git a/src/disco/metrics/generated/fd_metrics_net.h b/src/disco/metrics/generated/fd_metrics_net.h index b1bad7cca2..9b8ae06813 100644 --- a/src/disco/metrics/generated/fd_metrics_net.h +++ b/src/disco/metrics/generated/fd_metrics_net.h @@ -8,168 +8,172 @@ #define FD_METRICS_COUNTER_NET_RX_PKT_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_RX_PKT_CNT_DESC "Packet receive count." #define FD_METRICS_COUNTER_NET_RX_PKT_CNT_CVT (FD_METRICS_CONVERTER_NONE) +#define FD_METRICS_COUNTER_NET_RX_PKT_CNT_CNT (2UL) -#define FD_METRICS_COUNTER_NET_RX_BYTES_TOTAL_OFF (17UL) +#define FD_METRICS_COUNTER_NET_RX_PKT_CNT_IP4_UDP_OFF (16UL) +#define FD_METRICS_COUNTER_NET_RX_PKT_CNT_IP4_OPT_UDP_OFF (17UL) + +#define FD_METRICS_COUNTER_NET_RX_BYTES_TOTAL_OFF (18UL) #define FD_METRICS_COUNTER_NET_RX_BYTES_TOTAL_NAME "net_rx_bytes_total" #define FD_METRICS_COUNTER_NET_RX_BYTES_TOTAL_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_RX_BYTES_TOTAL_DESC "Total number of bytes received (including Ethernet header)." #define FD_METRICS_COUNTER_NET_RX_BYTES_TOTAL_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_RX_UNDERSZ_CNT_OFF (18UL) +#define FD_METRICS_COUNTER_NET_RX_UNDERSZ_CNT_OFF (19UL) #define FD_METRICS_COUNTER_NET_RX_UNDERSZ_CNT_NAME "net_rx_undersz_cnt" #define FD_METRICS_COUNTER_NET_RX_UNDERSZ_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_RX_UNDERSZ_CNT_DESC "Number of incoming packets dropped due to being too small." #define FD_METRICS_COUNTER_NET_RX_UNDERSZ_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_RX_FILL_BLOCKED_CNT_OFF (19UL) +#define FD_METRICS_COUNTER_NET_RX_FILL_BLOCKED_CNT_OFF (20UL) #define FD_METRICS_COUNTER_NET_RX_FILL_BLOCKED_CNT_NAME "net_rx_fill_blocked_cnt" #define FD_METRICS_COUNTER_NET_RX_FILL_BLOCKED_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_RX_FILL_BLOCKED_CNT_DESC "Number of incoming packets dropped due to fill ring being full." #define FD_METRICS_COUNTER_NET_RX_FILL_BLOCKED_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_RX_BACKPRESSURE_CNT_OFF (20UL) +#define FD_METRICS_COUNTER_NET_RX_BACKPRESSURE_CNT_OFF (21UL) #define FD_METRICS_COUNTER_NET_RX_BACKPRESSURE_CNT_NAME "net_rx_backpressure_cnt" #define FD_METRICS_COUNTER_NET_RX_BACKPRESSURE_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_RX_BACKPRESSURE_CNT_DESC "Number of incoming packets dropped due to backpressure." #define FD_METRICS_COUNTER_NET_RX_BACKPRESSURE_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_GAUGE_NET_RX_BUSY_CNT_OFF (21UL) +#define FD_METRICS_GAUGE_NET_RX_BUSY_CNT_OFF (22UL) #define FD_METRICS_GAUGE_NET_RX_BUSY_CNT_NAME "net_rx_busy_cnt" #define FD_METRICS_GAUGE_NET_RX_BUSY_CNT_TYPE (FD_METRICS_TYPE_GAUGE) #define FD_METRICS_GAUGE_NET_RX_BUSY_CNT_DESC "Number of receive buffers currently busy." #define FD_METRICS_GAUGE_NET_RX_BUSY_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_GAUGE_NET_RX_IDLE_CNT_OFF (22UL) +#define FD_METRICS_GAUGE_NET_RX_IDLE_CNT_OFF (23UL) #define FD_METRICS_GAUGE_NET_RX_IDLE_CNT_NAME "net_rx_idle_cnt" #define FD_METRICS_GAUGE_NET_RX_IDLE_CNT_TYPE (FD_METRICS_TYPE_GAUGE) #define FD_METRICS_GAUGE_NET_RX_IDLE_CNT_DESC "Number of receive buffers currently idle." #define FD_METRICS_GAUGE_NET_RX_IDLE_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_TX_SUBMIT_CNT_OFF (23UL) +#define FD_METRICS_COUNTER_NET_TX_SUBMIT_CNT_OFF (24UL) #define FD_METRICS_COUNTER_NET_TX_SUBMIT_CNT_NAME "net_tx_submit_cnt" #define FD_METRICS_COUNTER_NET_TX_SUBMIT_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_TX_SUBMIT_CNT_DESC "Number of packet transmit jobs submitted." #define FD_METRICS_COUNTER_NET_TX_SUBMIT_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_TX_COMPLETE_CNT_OFF (24UL) +#define FD_METRICS_COUNTER_NET_TX_COMPLETE_CNT_OFF (25UL) #define FD_METRICS_COUNTER_NET_TX_COMPLETE_CNT_NAME "net_tx_complete_cnt" #define FD_METRICS_COUNTER_NET_TX_COMPLETE_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_TX_COMPLETE_CNT_DESC "Number of packet transmit jobs marked as completed by the kernel." #define FD_METRICS_COUNTER_NET_TX_COMPLETE_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_TX_BYTES_TOTAL_OFF (25UL) +#define FD_METRICS_COUNTER_NET_TX_BYTES_TOTAL_OFF (26UL) #define FD_METRICS_COUNTER_NET_TX_BYTES_TOTAL_NAME "net_tx_bytes_total" #define FD_METRICS_COUNTER_NET_TX_BYTES_TOTAL_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_TX_BYTES_TOTAL_DESC "Total number of bytes transmitted (including Ethernet header)." #define FD_METRICS_COUNTER_NET_TX_BYTES_TOTAL_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_TX_ROUTE_FAIL_CNT_OFF (26UL) +#define FD_METRICS_COUNTER_NET_TX_ROUTE_FAIL_CNT_OFF (27UL) #define FD_METRICS_COUNTER_NET_TX_ROUTE_FAIL_CNT_NAME "net_tx_route_fail_cnt" #define FD_METRICS_COUNTER_NET_TX_ROUTE_FAIL_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_TX_ROUTE_FAIL_CNT_DESC "Number of packet transmit jobs dropped due to route failure." #define FD_METRICS_COUNTER_NET_TX_ROUTE_FAIL_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_TX_NEIGHBOR_FAIL_CNT_OFF (27UL) +#define FD_METRICS_COUNTER_NET_TX_NEIGHBOR_FAIL_CNT_OFF (28UL) #define FD_METRICS_COUNTER_NET_TX_NEIGHBOR_FAIL_CNT_NAME "net_tx_neighbor_fail_cnt" #define FD_METRICS_COUNTER_NET_TX_NEIGHBOR_FAIL_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_TX_NEIGHBOR_FAIL_CNT_DESC "Number of packet transmit jobs dropped due to unresolved neighbor." #define FD_METRICS_COUNTER_NET_TX_NEIGHBOR_FAIL_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_TX_FULL_FAIL_CNT_OFF (28UL) +#define FD_METRICS_COUNTER_NET_TX_FULL_FAIL_CNT_OFF (29UL) #define FD_METRICS_COUNTER_NET_TX_FULL_FAIL_CNT_NAME "net_tx_full_fail_cnt" #define FD_METRICS_COUNTER_NET_TX_FULL_FAIL_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_TX_FULL_FAIL_CNT_DESC "Number of packet transmit jobs dropped due to XDP TX ring full or missing completions." #define FD_METRICS_COUNTER_NET_TX_FULL_FAIL_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_GAUGE_NET_TX_BUSY_CNT_OFF (29UL) +#define FD_METRICS_GAUGE_NET_TX_BUSY_CNT_OFF (30UL) #define FD_METRICS_GAUGE_NET_TX_BUSY_CNT_NAME "net_tx_busy_cnt" #define FD_METRICS_GAUGE_NET_TX_BUSY_CNT_TYPE (FD_METRICS_TYPE_GAUGE) #define FD_METRICS_GAUGE_NET_TX_BUSY_CNT_DESC "Number of transmit buffers currently busy." #define FD_METRICS_GAUGE_NET_TX_BUSY_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_GAUGE_NET_TX_IDLE_CNT_OFF (30UL) +#define FD_METRICS_GAUGE_NET_TX_IDLE_CNT_OFF (31UL) #define FD_METRICS_GAUGE_NET_TX_IDLE_CNT_NAME "net_tx_idle_cnt" #define FD_METRICS_GAUGE_NET_TX_IDLE_CNT_TYPE (FD_METRICS_TYPE_GAUGE) #define FD_METRICS_GAUGE_NET_TX_IDLE_CNT_DESC "Number of transmit buffers currently idle." #define FD_METRICS_GAUGE_NET_TX_IDLE_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_XSK_TX_WAKEUP_CNT_OFF (31UL) +#define FD_METRICS_COUNTER_NET_XSK_TX_WAKEUP_CNT_OFF (32UL) #define FD_METRICS_COUNTER_NET_XSK_TX_WAKEUP_CNT_NAME "net_xsk_tx_wakeup_cnt" #define FD_METRICS_COUNTER_NET_XSK_TX_WAKEUP_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_XSK_TX_WAKEUP_CNT_DESC "Number of XSK sendto syscalls dispatched." #define FD_METRICS_COUNTER_NET_XSK_TX_WAKEUP_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_XSK_RX_WAKEUP_CNT_OFF (32UL) +#define FD_METRICS_COUNTER_NET_XSK_RX_WAKEUP_CNT_OFF (33UL) #define FD_METRICS_COUNTER_NET_XSK_RX_WAKEUP_CNT_NAME "net_xsk_rx_wakeup_cnt" #define FD_METRICS_COUNTER_NET_XSK_RX_WAKEUP_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_XSK_RX_WAKEUP_CNT_DESC "Number of XSK recvmsg syscalls dispatched." #define FD_METRICS_COUNTER_NET_XSK_RX_WAKEUP_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_XDP_RX_DROPPED_OTHER_OFF (33UL) +#define FD_METRICS_COUNTER_NET_XDP_RX_DROPPED_OTHER_OFF (34UL) #define FD_METRICS_COUNTER_NET_XDP_RX_DROPPED_OTHER_NAME "net_xdp_rx_dropped_other" #define FD_METRICS_COUNTER_NET_XDP_RX_DROPPED_OTHER_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_XDP_RX_DROPPED_OTHER_DESC "xdp_statistics_v0.rx_dropped: Dropped for other reasons" #define FD_METRICS_COUNTER_NET_XDP_RX_DROPPED_OTHER_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_XDP_RX_INVALID_DESCS_OFF (34UL) +#define FD_METRICS_COUNTER_NET_XDP_RX_INVALID_DESCS_OFF (35UL) #define FD_METRICS_COUNTER_NET_XDP_RX_INVALID_DESCS_NAME "net_xdp_rx_invalid_descs" #define FD_METRICS_COUNTER_NET_XDP_RX_INVALID_DESCS_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_XDP_RX_INVALID_DESCS_DESC "xdp_statistics_v0.rx_invalid_descs: Dropped due to invalid descriptor" #define FD_METRICS_COUNTER_NET_XDP_RX_INVALID_DESCS_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_XDP_TX_INVALID_DESCS_OFF (35UL) +#define FD_METRICS_COUNTER_NET_XDP_TX_INVALID_DESCS_OFF (36UL) #define FD_METRICS_COUNTER_NET_XDP_TX_INVALID_DESCS_NAME "net_xdp_tx_invalid_descs" #define FD_METRICS_COUNTER_NET_XDP_TX_INVALID_DESCS_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_XDP_TX_INVALID_DESCS_DESC "xdp_statistics_v0.tx_invalid_descs: Dropped due to invalid descriptor" #define FD_METRICS_COUNTER_NET_XDP_TX_INVALID_DESCS_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_XDP_RX_RING_FULL_OFF (36UL) +#define FD_METRICS_COUNTER_NET_XDP_RX_RING_FULL_OFF (37UL) #define FD_METRICS_COUNTER_NET_XDP_RX_RING_FULL_NAME "net_xdp_rx_ring_full" #define FD_METRICS_COUNTER_NET_XDP_RX_RING_FULL_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_XDP_RX_RING_FULL_DESC "xdp_statistics_v1.rx_ring_full: Dropped due to rx ring being full" #define FD_METRICS_COUNTER_NET_XDP_RX_RING_FULL_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_XDP_RX_FILL_RING_EMPTY_DESCS_OFF (37UL) +#define FD_METRICS_COUNTER_NET_XDP_RX_FILL_RING_EMPTY_DESCS_OFF (38UL) #define FD_METRICS_COUNTER_NET_XDP_RX_FILL_RING_EMPTY_DESCS_NAME "net_xdp_rx_fill_ring_empty_descs" #define FD_METRICS_COUNTER_NET_XDP_RX_FILL_RING_EMPTY_DESCS_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_XDP_RX_FILL_RING_EMPTY_DESCS_DESC "xdp_statistics_v1.rx_fill_ring_empty_descs: Failed to retrieve item from fill ring" #define FD_METRICS_COUNTER_NET_XDP_RX_FILL_RING_EMPTY_DESCS_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_XDP_TX_RING_EMPTY_DESCS_OFF (38UL) +#define FD_METRICS_COUNTER_NET_XDP_TX_RING_EMPTY_DESCS_OFF (39UL) #define FD_METRICS_COUNTER_NET_XDP_TX_RING_EMPTY_DESCS_NAME "net_xdp_tx_ring_empty_descs" #define FD_METRICS_COUNTER_NET_XDP_TX_RING_EMPTY_DESCS_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_XDP_TX_RING_EMPTY_DESCS_DESC "xdp_statistics_v1.tx_ring_empty_descs: Failed to retrieve item from tx ring" #define FD_METRICS_COUNTER_NET_XDP_TX_RING_EMPTY_DESCS_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_RX_GRE_CNT_OFF (39UL) +#define FD_METRICS_COUNTER_NET_RX_GRE_CNT_OFF (40UL) #define FD_METRICS_COUNTER_NET_RX_GRE_CNT_NAME "net_rx_gre_cnt" #define FD_METRICS_COUNTER_NET_RX_GRE_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_RX_GRE_CNT_DESC "Number of valid GRE packets received" #define FD_METRICS_COUNTER_NET_RX_GRE_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_RX_GRE_INVALID_CNT_OFF (40UL) +#define FD_METRICS_COUNTER_NET_RX_GRE_INVALID_CNT_OFF (41UL) #define FD_METRICS_COUNTER_NET_RX_GRE_INVALID_CNT_NAME "net_rx_gre_invalid_cnt" #define FD_METRICS_COUNTER_NET_RX_GRE_INVALID_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_RX_GRE_INVALID_CNT_DESC "Number of invalid GRE packets received" #define FD_METRICS_COUNTER_NET_RX_GRE_INVALID_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_RX_GRE_IGNORED_CNT_OFF (41UL) +#define FD_METRICS_COUNTER_NET_RX_GRE_IGNORED_CNT_OFF (42UL) #define FD_METRICS_COUNTER_NET_RX_GRE_IGNORED_CNT_NAME "net_rx_gre_ignored_cnt" #define FD_METRICS_COUNTER_NET_RX_GRE_IGNORED_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_RX_GRE_IGNORED_CNT_DESC "Number of received but ignored GRE packets" #define FD_METRICS_COUNTER_NET_RX_GRE_IGNORED_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_TX_GRE_CNT_OFF (42UL) +#define FD_METRICS_COUNTER_NET_TX_GRE_CNT_OFF (43UL) #define FD_METRICS_COUNTER_NET_TX_GRE_CNT_NAME "net_tx_gre_cnt" #define FD_METRICS_COUNTER_NET_TX_GRE_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_TX_GRE_CNT_DESC "Number of GRE packet transmit jobs submitted" #define FD_METRICS_COUNTER_NET_TX_GRE_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_COUNTER_NET_TX_GRE_ROUTE_FAIL_CNT_OFF (43UL) +#define FD_METRICS_COUNTER_NET_TX_GRE_ROUTE_FAIL_CNT_OFF (44UL) #define FD_METRICS_COUNTER_NET_TX_GRE_ROUTE_FAIL_CNT_NAME "net_tx_gre_route_fail_cnt" #define FD_METRICS_COUNTER_NET_TX_GRE_ROUTE_FAIL_CNT_TYPE (FD_METRICS_TYPE_COUNTER) #define FD_METRICS_COUNTER_NET_TX_GRE_ROUTE_FAIL_CNT_DESC "Number of GRE packets transmit jobs dropped due to route failure" #define FD_METRICS_COUNTER_NET_TX_GRE_ROUTE_FAIL_CNT_CVT (FD_METRICS_CONVERTER_NONE) -#define FD_METRICS_NET_TOTAL (28UL) +#define FD_METRICS_NET_TOTAL (29UL) extern const fd_metrics_meta_t FD_METRICS_NET[FD_METRICS_NET_TOTAL]; diff --git a/src/disco/metrics/metrics.xml b/src/disco/metrics/metrics.xml index 0de555fb6a..1867163465 100644 --- a/src/disco/metrics/metrics.xml +++ b/src/disco/metrics/metrics.xml @@ -51,8 +51,13 @@ metric introduced. + + + + + - + diff --git a/src/disco/net/Local.mk b/src/disco/net/Local.mk index 0299677e5e..463cc1a639 100644 --- a/src/disco/net/Local.mk +++ b/src/disco/net/Local.mk @@ -2,3 +2,6 @@ ifdef FD_HAS_ALLOCA $(call add-hdrs,fd_net_tile.h) $(call add-objs,fd_net_tile_topo,fd_disco) endif +$(call add-hdrs,fd_find_16x16.h) +$(call make-unit-test,test_find_16x16,test_find_16x16,fd_util) +$(call run-unit-test,test_find_16x16) diff --git a/src/disco/net/fd_find_16x16.h b/src/disco/net/fd_find_16x16.h new file mode 100644 index 0000000000..f127a7ffda --- /dev/null +++ b/src/disco/net/fd_find_16x16.h @@ -0,0 +1,47 @@ +#ifndef HEADER_fd_src_disco_net_fd_find_16x16_h +#define HEADER_fd_src_disco_net_fd_find_16x16_h + +/* fd_find_16x16() provides an API to find an element in ushort[ 16 ]. + + If multiple elements match, returns the one at the lowest index. + If no element matched, returns 16. */ + +#include "../../util/fd_util_base.h" + +#if FD_HAS_AVX + +#include "../../util/simd/fd_avx.h" + +static inline uint +fd_find_16x16_avx( wu_t const ymm, + ushort x ) { + wc_t cmp_res = wh_eq( ymm, wh_bcast( x ) ); + uint mask = (uint)_mm256_movemask_epi8( cmp_res ); +#if defined(__LZNCT__) + int lane_idx = _lzcnt_u32( mask ); /* lane_idx==32 if mask==0 */ +#else + int lane_idx = fd_uint_find_lsb_w_default( mask, 32 ); +#endif + return ((uint)lane_idx)>>1; +} + +#endif + +static inline uint +fd_find_16x16_generic( ushort const ele[ 16 ], + ushort x ) { + /* Generates surprisingly bad code on GCC 15 and Clang 20 */ + uint i; + for( i=0; i<16; i++ ) { + if( ele[ i ]==x ) break; + } + return i; +} + +#if FD_HAS_AVX +static inline uint fd_find_16x16( ushort const ele[ 16 ], ushort x ) { return fd_find_16x16_avx( wu_ldu( ele ),x ); } +#else +#define fd_find_16x16 fd_find_16x16_generic +#endif + +#endif /* HEADER_fd_src_disco_net_fd_find_16x16_h */ diff --git a/src/disco/net/fd_net_common.h b/src/disco/net/fd_net_common.h deleted file mode 100644 index 91dc63b129..0000000000 --- a/src/disco/net/fd_net_common.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef HEADER_fd_src_disco_net_fd_net_common_h -#define HEADER_fd_src_disco_net_fd_net_common_h - -/* fd_net_common.h contains common definitions across net tile implementations. */ - -/* REPAIR_PING_SZ is the sz of a ping packet for the repair protocol. - Because pings are routed to the same port as shreds without any - discriminant encoding, we have to use the packet sz to interpret the - payload. Note that any valid shred must be either FD_SHRED_MAX_SZ - or FD_SHRED_MIN_SZ ie. will never be FD_REPAIR_PING_SZ.*/ - -#define REPAIR_PING_SZ (174UL) - -#endif /* HEADER_fd_src_disco_net_fd_net_common_h */ diff --git a/src/disco/net/sock/fd_sock_tile.c b/src/disco/net/sock/fd_sock_tile.c index 65cfc53b17..a0e15faf63 100644 --- a/src/disco/net/sock/fd_sock_tile.c +++ b/src/disco/net/sock/fd_sock_tile.c @@ -1,6 +1,5 @@ #define _GNU_SOURCE /* dup3 */ #include "fd_sock_tile_private.h" -#include "../fd_net_common.h" #include "../../topo/fd_topo.h" #include "../../../util/net/fd_eth.h" #include "../../../util/net/fd_ip4.h" @@ -29,11 +28,6 @@ Must be aligned by alignof(struct cmsghdr) */ #define FD_SOCK_CMSG_MAX (64UL) -/* Value of the sock_idx for Firedancer repair intake. - Used to determine whether repair packets should go to shred vs repair tile. - This value is validated at startup. */ -#define REPAIR_SHRED_SOCKET_ID (4U) - static ulong populate_allowed_seccomp( fd_topo_t const * topo, fd_topo_tile_t const * tile, @@ -185,49 +179,17 @@ privileged_init( fd_topo_t * topo, descriptors starting at sock_fd_min. */ int sock_fd_min = RX_SOCK_FD_MIN; - ushort udp_port_candidates[] = { - (ushort)tile->sock.net.legacy_transaction_listen_port, - (ushort)tile->sock.net.quic_transaction_listen_port, - (ushort)tile->sock.net.shred_listen_port, - (ushort)tile->sock.net.gossip_listen_port, - (ushort)tile->sock.net.repair_intake_listen_port, - (ushort)tile->sock.net.repair_serve_listen_port, - (ushort)tile->sock.net.send_src_port - }; - static char const * udp_port_links[] = { - "net_quic", /* legacy_transaction_listen_port */ - "net_quic", /* quic_transaction_listen_port */ - "net_shred", /* shred_listen_port (turbine) */ - "net_gossip", /* gossip_listen_port */ - "net_shred", /* shred_listen_port (repair) */ - "net_repair", /* repair_serve_listen_port */ - "net_send" /* send_src_port */ - }; - static uchar const udp_port_protos[] = { - DST_PROTO_TPU_UDP, /* legacy_transaction_listen_port */ - DST_PROTO_TPU_QUIC, /* quic_transaction_listen_port */ - DST_PROTO_SHRED, /* shred_listen_port (turbine) */ - DST_PROTO_GOSSIP, /* gossip_listen_port */ - DST_PROTO_REPAIR, /* shred_listen_port (repair) */ - DST_PROTO_REPAIR /* repair_serve_listen_port */ - }; - for( uint candidate_idx=0U; candidate_idx<6; candidate_idx++ ) { - if( !udp_port_candidates[ candidate_idx ] ) continue; - uint sock_idx = ctx->sock_cnt; - if( candidate_idx>FD_SOCK_TILE_MAX_SOCKETS ) FD_LOG_ERR(( "too many sockets" )); - ushort port = (ushort)udp_port_candidates[ candidate_idx ]; - - /* Validate value of REPAIR_SHRED_SOCKET_ID */ - if( udp_port_candidates[sock_idx]==tile->sock.net.repair_intake_listen_port ) - FD_TEST( sock_idx==REPAIR_SHRED_SOCKET_ID ); - if( udp_port_candidates[sock_idx]==tile->sock.net.repair_serve_listen_port ) - FD_TEST( sock_idx==REPAIR_SHRED_SOCKET_ID+1 ); - - char const * target_link = udp_port_links[ candidate_idx ]; + ulong const rule_cnt = tile->net.rx_rules.rx_rule_cnt; + for( uint rule_idx=0U; rule_idxnet.rx_rules.rx_rules[ rule_idx ]; + uint const sock_idx = ctx->sock_cnt; + ushort const port = (ushort)rule->port; + + char const * target_link = rule->link; ctx->link_rx_map[ sock_idx ] = 0xFF; for( ulong j=0UL; j<(tile->out_cnt); j++ ) { if( 0==strcmp( topo->links[ tile->out_link_id[ j ] ].name, target_link ) ) { - ctx->proto_id [ sock_idx ] = (uchar)udp_port_protos[ candidate_idx ]; + ctx->proto_id [ sock_idx ] = (uchar)rule->proto_id; ctx->link_rx_map [ sock_idx ] = (uchar)j; ctx->rx_sock_port[ sock_idx ] = (ushort)port; break; @@ -411,18 +373,7 @@ poll_rx_socket( fd_sock_tile_t * ctx, ulong sig = fd_disco_netmux_sig( sa->sin_addr.s_addr, fd_ushort_bswap( sa->sin_port ), sa->sin_addr.s_addr, proto, hdr_sz ); ulong tspub = fd_frag_meta_ts_comp( ts ); - /* default for repair intake is to send to [shreds] to shred tile. - ping messages should be routed to the repair. */ - if( FD_UNLIKELY( sock_idx==REPAIR_SHRED_SOCKET_ID && frame_sz==REPAIR_PING_SZ ) ) { - uchar repair_rx_link = ctx->link_rx_map[ REPAIR_SHRED_SOCKET_ID+1 ]; - fd_sock_link_rx_t * repair_link = ctx->link_rx + repair_rx_link; - uchar * repair_buf = fd_chunk_to_laddr( repair_link->base, repair_link->chunk ); - memcpy( repair_buf, eth_hdr, frame_sz ); - fd_stem_publish( stem, repair_rx_link, sig, repair_link->chunk, frame_sz, 0UL, 0UL, tspub ); - repair_link->chunk = fd_dcache_compact_next( repair_link->chunk, FD_NET_MTU, repair_link->chunk0, repair_link->wmark ); - } else { - fd_stem_publish( stem, rx_link, sig, chunk, frame_sz, 0UL, 0UL, tspub ); - } + fd_stem_publish( stem, rx_link, sig, chunk, frame_sz, 0UL, 0UL, tspub ); last_chunk = chunk; } diff --git a/src/disco/net/sock/fd_sock_tile_private.h b/src/disco/net/sock/fd_sock_tile_private.h index d404940141..1865df789d 100644 --- a/src/disco/net/sock/fd_sock_tile_private.h +++ b/src/disco/net/sock/fd_sock_tile_private.h @@ -3,7 +3,7 @@ #if FD_HAS_HOSTED -#include "../../../util/fd_util_base.h" +#include "../../topo/fd_topo.h" #include "../../metrics/generated/fd_metrics_enums.h" #include #include @@ -11,7 +11,7 @@ /* FD_SOCK_TILE_MAX_SOCKETS controls the max number of UDP ports that a sock tile can bind to. */ -#define FD_SOCK_TILE_MAX_SOCKETS (8) +#define FD_SOCK_TILE_MAX_SOCKETS FD_TOPO_NET_RX_RULE_MAX /* MAX_NET_INS controls the max number of TX links that a sock tile can serve. */ diff --git a/src/disco/net/test_find_16x16.c b/src/disco/net/test_find_16x16.c new file mode 100644 index 0000000000..7bb419553e --- /dev/null +++ b/src/disco/net/test_find_16x16.c @@ -0,0 +1,28 @@ +/* Bit wasteful to have this as a separate test executable, consider + merging this with another test. */ + +#include "../../util/fd_util.h" +#include "fd_find_16x16.h" + +int +main( int argc, + char ** argv ) { + fd_boot( &argc, &argv ); + + ushort ti[16]; +#define INIT_TI( EXPR ) do { for( ulong j=0UL; j<16UL; j++ ) { ti[j] = (EXPR); } } while( 0 ) + + INIT_TI( 0 ); + FD_TEST( fd_find_16x16( ti, 0 )==0 ); + for( ulong j=0UL; j<16UL; j++ ) { + ti[ j ] = (ushort)( USHORT_MAX-j ); + FD_TEST( fd_find_16x16( ti, 0 )==j+1UL ); + FD_TEST( fd_find_16x16( ti, ti[ j ] )==j ); + } + +#undef INIT_TI + + FD_LOG_NOTICE(( "pass" )); + fd_halt(); + return 0; +} diff --git a/src/disco/net/xdp/fd_xdp_tile.c b/src/disco/net/xdp/fd_xdp_tile.c index f54b9d2eed..4382735811 100644 --- a/src/disco/net/xdp/fd_xdp_tile.c +++ b/src/disco/net/xdp/fd_xdp_tile.c @@ -9,7 +9,7 @@ #include /* MSG_DONTWAIT needed before importing the net seccomp filter */ #include -#include "../fd_net_common.h" +#include "../fd_find_16x16.h" #include "../../metrics/fd_metrics.h" #include "../../netlink/fd_netlink_tile.h" /* neigh4_solicit */ #include "../../topo/fd_topo.h" @@ -38,6 +38,13 @@ #define MAX_NET_INS (32UL) +/* MAX_NET_OUTS controls the max number of RX-to-tango forwarding links + that a net tile can serve. Also bounds the number of UDP listen + ports. Not trivial to change because of algorithms optimized for + this particular value (fd_find_16x16). */ + +#define MAX_NET_OUTS (16UL) + /* FD_XDP_STATS_INTERVAL_NS controls the XDP stats refresh interval. This should be lower than the interval at which the metrics tile collects metrics. */ @@ -158,6 +165,12 @@ struct fd_net_free_ring { }; typedef struct fd_net_free_ring fd_net_free_ring_t; +struct fd_xdp_rx_rule { + ushort port; + ushort out_idx; +}; +typedef struct fd_xdp_rx_rule fd_xdp_rx_rule_t; + typedef struct { /* An "XSK" is an AF_XDP socket */ uint xsk_cnt; @@ -198,27 +211,32 @@ typedef struct { /* Ring tracking free packet buffers */ fd_net_free_ring_t free_tx; - uchar src_mac_addr[6]; + uint default_address; + uint bind_address; - uint default_address; - uint bind_address; - ushort shred_listen_port; - ushort quic_transaction_listen_port; - ushort legacy_transaction_listen_port; - ushort gossip_listen_port; - ushort repair_intake_listen_port; - ushort repair_serve_listen_port; - ushort send_src_port; + /* RX flow steering (by UDP ports) */ + uint rx_port_cnt; /* in [0,MAX_NET_OUTS) */ + + union { +#if FD_HAS_AVX + wh_t wh[1]; /* forces alignment */ +#endif + ushort h[16]; + } rx_port_keys; + + struct { + uchar dst_proto; + uchar out_link_idx; + } rx_port_vals[ MAX_NET_OUTS ]; + /* Tango out links. Only initialized for RX packet links, not for + management plane links (e.g. netlink). */ + fd_net_out_ctx_t out[ MAX_NET_OUTS ]; + + /* Tango in links (for TX packet jobs) */ ulong in_cnt; fd_net_in_ctx_t in[ MAX_NET_INS ]; - fd_net_out_ctx_t quic_out[1]; - fd_net_out_ctx_t shred_out[1]; - fd_net_out_ctx_t gossip_out[1]; - fd_net_out_ctx_t repair_out[1]; - fd_net_out_ctx_t send_out[1]; - /* XDP stats refresh timer */ long xdp_stats_interval_ticks; long next_xdp_stats_refresh; @@ -240,7 +258,8 @@ typedef struct { int has_gre_interface; /* enable GRE support? */ struct { - ulong rx_pkt_cnt; + ulong rx_pkt_cnt_ip4_udp; + ulong rx_pkt_cnt_ip4_opt_udp; ulong rx_bytes_total; ulong rx_undersz_cnt; ulong rx_fill_blocked_cnt; @@ -285,7 +304,8 @@ scratch_footprint( fd_topo_tile_t const * tile ) { static void metrics_write( fd_net_ctx_t * ctx ) { - FD_MCNT_SET( NET, RX_PKT_CNT, ctx->metrics.rx_pkt_cnt ); + FD_MCNT_SET( NET, RX_PKT_CNT_IP4_UDP, ctx->metrics.rx_pkt_cnt_ip4_udp ); + FD_MCNT_SET( NET, RX_PKT_CNT_IP4_OPT_UDP, ctx->metrics.rx_pkt_cnt_ip4_opt_udp ); FD_MCNT_SET( NET, RX_BYTES_TOTAL, ctx->metrics.rx_bytes_total ); FD_MCNT_SET( NET, RX_UNDERSZ_CNT, ctx->metrics.rx_undersz_cnt ); FD_MCNT_SET( NET, RX_FILL_BLOCKED_CNT, ctx->metrics.rx_fill_blocked_cnt ); @@ -937,8 +957,8 @@ net_rx_packet( fd_net_ctx_t * ctx, ( iphdr->protocol!=FD_IP4_HDR_PROTOCOL_UDP ) ) ) return; /* IPv4 is variable-length, so lookup IHL to find start of UDP */ - uint iplen = FD_IP4_GET_LEN( *iphdr ); - uchar const * udp = (uchar *)iphdr + iplen; + uint iplen = FD_IP4_GET_LEN( *iphdr ); + uchar const * udp = (uchar *)iphdr + iplen; if( FD_UNLIKELY( udp+sizeof(fd_udp_hdr_t) > packet_end ) ) { FD_DTRACE_PROBE( net_tile_err_rx_undersz ); @@ -955,45 +975,31 @@ net_rx_packet( fd_net_ctx_t * ctx, FD_DTRACE_PROBE_4( net_tile_pkt_rx, ip_srcaddr, udp_srcport, udp_dstport, sz ); /* Route packet to downstream tile */ - ushort proto; - fd_net_out_ctx_t * out; - if( FD_UNLIKELY( udp_dstport==ctx->shred_listen_port ) ) { - proto = DST_PROTO_SHRED; - out = ctx->shred_out; - } else if( FD_UNLIKELY( udp_dstport==ctx->quic_transaction_listen_port ) ) { - proto = DST_PROTO_TPU_QUIC; - out = ctx->quic_out; - } else if( FD_UNLIKELY( udp_dstport==ctx->legacy_transaction_listen_port ) ) { - proto = DST_PROTO_TPU_UDP; - out = ctx->quic_out; - } else if( FD_UNLIKELY( udp_dstport==ctx->gossip_listen_port ) ) { - proto = DST_PROTO_GOSSIP; - out = ctx->gossip_out; - } else if( FD_UNLIKELY( udp_dstport==ctx->repair_intake_listen_port ) ) { - proto = DST_PROTO_REPAIR; - if( FD_UNLIKELY( sz == REPAIR_PING_SZ ) ) out = ctx->repair_out; /* ping-pong */ - else out = ctx->shred_out; - } else if( FD_UNLIKELY( udp_dstport==ctx->repair_serve_listen_port ) ) { - proto = DST_PROTO_REPAIR; - out = ctx->repair_out; - } else if( FD_UNLIKELY( udp_dstport==ctx->send_src_port ) ) { - proto = DST_PROTO_SEND; - out = ctx->send_out; - } else { +#if FD_HAS_AVX + uint port_idx = fd_find_16x16_avx( *ctx->rx_port_keys.wh, udp_dstport ); +#else + uint port_idx = fd_find_16x16( ctx->rx_port_keys.h, udp_dstport ); +#endif + if( FD_UNLIKELY( port_idx >= ctx->rx_port_cnt ) ) { + /* Dump out the listen port configuration to aid debugging */ + FD_LOG_NOTICE(( "Fatal error occurred.\nDumping XDP RX UDP port configuration to aid debugging:" )); + for( uint i=0UL; irx_port_cnt; i++ ) { + FD_LOG_NOTICE(( " ( idx=%u udp.dport=%hu proto=%x out_link_idx=%u )", + i, + ctx->rx_port_keys.h[ i ], + ctx->rx_port_vals[ i ].dst_proto, + ctx->rx_port_vals[ i ].out_link_idx )); + } FD_LOG_ERR(( "Firedancer received a UDP packet on port %hu which was not expected. " - "Only the following ports should be configured to forward packets: " - "%hu, %hu, %hu, %hu, %hu, %hu (excluding any 0 ports, which can be ignored)." - "Please report this error to Firedancer maintainers.", - udp_dstport, - ctx->shred_listen_port, - ctx->quic_transaction_listen_port, - ctx->legacy_transaction_listen_port, - ctx->gossip_listen_port, - ctx->repair_intake_listen_port, - ctx->repair_serve_listen_port )); + "Please report this error to Firedancer maintainers along with your config file.", + udp_dstport )); } + uint out_idx = ctx->rx_port_vals[ port_idx ].out_link_idx; + ushort proto = ctx->rx_port_vals[ port_idx ].dst_proto; + fd_net_out_ctx_t * out = &ctx->out[ out_idx ]; + /* tile can decide how to partition based on src ip addr and src port */ ulong sig = fd_disco_netmux_sig( ip_srcaddr, udp_srcport, ip_srcaddr, proto, 14UL+8UL+iplen ); @@ -1009,7 +1015,10 @@ net_rx_packet( fd_net_ctx_t * ctx, out->seq = fd_seq_inc( out->seq, 1UL ); if( is_packet_gre ) ctx->metrics.rx_gre_cnt++; - ctx->metrics.rx_pkt_cnt++; + ulong * rx_metric = iplen==sizeof(fd_ip4_hdr_t) ? + &ctx->metrics.rx_pkt_cnt_ip4_udp : + &ctx->metrics.rx_pkt_cnt_ip4_opt_udp; + (*rx_metric)++; ctx->metrics.rx_bytes_total += sz; } @@ -1177,20 +1186,15 @@ net_xsk_bootstrap( fd_net_ctx_t * ctx, return frame_off; } -/* FIXME source MAC address from netlnk tile instead */ +/* FIXME get default IPv4 address from netdev tbl instead */ static void interface_addrs( const char * interface, - uchar * mac, uint * ip4_addr ) { int fd = socket( AF_INET, SOCK_DGRAM, 0 ); struct ifreq ifr; ifr.ifr_addr.sa_family = AF_INET; - strncpy( ifr.ifr_name, interface, IFNAMSIZ ); - if( FD_UNLIKELY( ioctl( fd, SIOCGIFHWADDR, &ifr ) ) ) - FD_LOG_ERR(( "could not get MAC address of interface `%s`: (%i-%s)", interface, errno, fd_io_strerror( errno ) )); - fd_memcpy( mac, ifr.ifr_hwaddr.sa_data, 6 ); if( FD_UNLIKELY( ioctl( fd, SIOCGIFADDR, &ifr ) ) ) FD_LOG_ERR(( "could not get IP address of interface `%s`: (%i-%s)", interface, errno, fd_io_strerror( errno ) )); @@ -1234,7 +1238,7 @@ privileged_init( fd_topo_t * topo, uint if_idx = if_nametoindex( tile->xdp.interface ); if( FD_UNLIKELY( !if_idx ) ) FD_LOG_ERR(( "if_nametoindex(%s) failed", tile->xdp.interface )); - interface_addrs( tile->xdp.interface, ctx->src_mac_addr, &ctx->default_address ); + interface_addrs( tile->xdp.interface, &ctx->default_address ); /* Load up dcache containing UMEM */ @@ -1310,15 +1314,11 @@ privileged_init( fd_topo_t * topo, if( FD_UNLIKELY( strcmp( tile->xdp.interface, "lo" ) && !tile->kind_id ) ) { ctx->xsk_cnt = 2; - ushort udp_port_candidates[] = { - (ushort)tile->xdp.net.legacy_transaction_listen_port, - (ushort)tile->xdp.net.quic_transaction_listen_port, - (ushort)tile->xdp.net.shred_listen_port, - (ushort)tile->xdp.net.gossip_listen_port, - (ushort)tile->xdp.net.repair_intake_listen_port, - (ushort)tile->xdp.net.repair_serve_listen_port, - (ushort)tile->xdp.net.send_src_port - }; + ulong const rule_cnt = tile->net.rx_rules.rx_rule_cnt; + ushort udp_port_candidates[ FD_TOPO_NET_RX_RULE_MAX ]; + for( ulong i=0UL; inet.rx_rules.rx_rules[ i ].port; + } uint lo_idx = if_nametoindex( "lo" ); if( FD_UNLIKELY( !lo_idx ) ) FD_LOG_ERR(( "if_nametoindex(lo) failed" )); @@ -1326,7 +1326,7 @@ privileged_init( fd_topo_t * topo, /* FIXME move this to fd_topo_run */ fd_xdp_fds_t lo_fds = fd_xdp_install( lo_idx, tile->net.bind_address, - sizeof(udp_port_candidates)/sizeof(udp_port_candidates[0]), + rule_cnt, udp_port_candidates, "skb" ); @@ -1373,6 +1373,42 @@ init_device_table( fd_net_ctx_t * ctx, } +/* setup_out_link ensures an output link is set up for the given link + name. Idempotent. */ + +static uint +setup_out_link( fd_net_ctx_t * ctx, + fd_topo_t const * topo, + fd_topo_tile_t const * tile, + char const * link_name, + ulong tile_kind_id ) { + /* For a given output link kind (e.g. "net_quic"), each net tile + produces one output link, even if there are multiple downstream + consumer tiles. Each consumer tile receives all frags, but skips + frags based on a shared load balancing policy, making the tiles + effectively take turns processing frags. */ + ulong out_link_idx = fd_topo_find_tile_out_link( topo, tile, link_name, tile_kind_id ); + if( FD_UNLIKELY( out_link_idx==ULONG_MAX ) ) { + FD_LOG_ERR(( "link \"%s\" is not an output links of net:%lu", link_name, tile_kind_id )); + } + if( FD_UNLIKELY( out_link_idx>=MAX_NET_OUTS ) ) { + FD_LOG_ERR(( "out link \"%s\" out of bounds: index %lu >= MAX_NET_OUTS (%lu)", link_name, out_link_idx, (ulong)MAX_NET_OUTS )); + } + + fd_net_out_ctx_t * out_ctx = &ctx->out[ out_link_idx ]; + if( !out_ctx->mcache ) { + /* First time initialization */ + ulong const link_id = tile->out_link_id[ out_link_idx ]; + fd_topo_link_t const * out_link = &topo->links[ link_id ]; + if( FD_UNLIKELY( !out_link->mcache ) ) FD_LOG_CRIT(( "out_link[%lu]->mcache is NULL (missing topo_fill?)", out_link_idx )); + out_ctx->mcache = out_link->mcache; + out_ctx->depth = fd_mcache_depth ( out_ctx->mcache ); + out_ctx->sync = fd_mcache_seq_laddr( out_ctx->mcache ); + } + + return (uint)out_link_idx; +} + FD_FN_UNUSED static void unprivileged_init( fd_topo_t * topo, fd_topo_tile_t * tile ) { @@ -1388,17 +1424,9 @@ unprivileged_init( fd_topo_t * topo, ctx->net_tile_id = (uint)tile->kind_id; ctx->net_tile_cnt = (uint)fd_topo_tile_name_cnt( topo, tile->name ); - ctx->bind_address = tile->net.bind_address; - ctx->shred_listen_port = tile->net.shred_listen_port; - ctx->quic_transaction_listen_port = tile->net.quic_transaction_listen_port; - ctx->legacy_transaction_listen_port = tile->net.legacy_transaction_listen_port; - ctx->gossip_listen_port = tile->net.gossip_listen_port; - ctx->repair_intake_listen_port = tile->net.repair_intake_listen_port; - ctx->repair_serve_listen_port = tile->net.repair_serve_listen_port; - ctx->send_src_port = tile->net.send_src_port; + ctx->bind_address = tile->net.bind_address; - /* Put a bound on chunks we read from the input, to make sure they - are within in the data region of the workspace. */ + /* Net TX links (tango input links from net tile POV) */ if( FD_UNLIKELY( !tile->in_cnt ) ) FD_LOG_ERR(( "net tile in link cnt is zero" )); if( FD_UNLIKELY( tile->in_cnt>MAX_NET_INS ) ) FD_LOG_ERR(( "net tile in link cnt %lu exceeds MAX_NET_INS %lu", tile->in_cnt, MAX_NET_INS )); @@ -1412,74 +1440,28 @@ unprivileged_init( fd_topo_t * topo, ctx->in[ i ].wmark = fd_dcache_compact_wmark( ctx->in[ i ].mem, link->dcache, link->mtu ); } - for( ulong i = 0; i < tile->out_cnt; i++ ) { - fd_topo_link_t * out_link = &topo->links[ tile->out_link_id[ i ] ]; - if( strcmp( out_link->name, "net_quic" ) == 0 ) { - fd_topo_link_t * quic_out = out_link; - ctx->quic_out->mcache = quic_out->mcache; - ctx->quic_out->sync = fd_mcache_seq_laddr( ctx->quic_out->mcache ); - ctx->quic_out->depth = fd_mcache_depth( ctx->quic_out->mcache ); - ctx->quic_out->seq = fd_mcache_seq_query( ctx->quic_out->sync ); - } else if( strcmp( out_link->name, "net_shred" ) == 0 ) { - fd_topo_link_t * shred_out = out_link; - ctx->shred_out->mcache = shred_out->mcache; - ctx->shred_out->sync = fd_mcache_seq_laddr( ctx->shred_out->mcache ); - ctx->shred_out->depth = fd_mcache_depth( ctx->shred_out->mcache ); - ctx->shred_out->seq = fd_mcache_seq_query( ctx->shred_out->sync ); - } else if( strcmp( out_link->name, "net_gossip" ) == 0 ) { - fd_topo_link_t * gossip_out = out_link; - ctx->gossip_out->mcache = gossip_out->mcache; - ctx->gossip_out->sync = fd_mcache_seq_laddr( ctx->gossip_out->mcache ); - ctx->gossip_out->depth = fd_mcache_depth( ctx->gossip_out->mcache ); - ctx->gossip_out->seq = fd_mcache_seq_query( ctx->gossip_out->sync ); - } else if( strcmp( out_link->name, "net_repair" ) == 0 ) { - fd_topo_link_t * repair_out = out_link; - ctx->repair_out->mcache = repair_out->mcache; - ctx->repair_out->sync = fd_mcache_seq_laddr( ctx->repair_out->mcache ); - ctx->repair_out->depth = fd_mcache_depth( ctx->repair_out->mcache ); - ctx->repair_out->seq = fd_mcache_seq_query( ctx->repair_out->sync ); - } else if( strcmp( out_link->name, "net_netlnk" ) == 0 ) { - fd_topo_link_t * netlink_out = out_link; - ctx->neigh4_solicit->mcache = netlink_out->mcache; - ctx->neigh4_solicit->depth = fd_mcache_depth( ctx->neigh4_solicit->mcache ); - ctx->neigh4_solicit->seq = fd_mcache_seq_query( fd_mcache_seq_laddr( ctx->neigh4_solicit->mcache ) ); - } else if( strcmp( out_link->name, "net_send" ) == 0 ) { - fd_topo_link_t * send_out = out_link; - ctx->send_out->mcache = send_out->mcache; - ctx->send_out->sync = fd_mcache_seq_laddr( ctx->send_out->mcache ); - ctx->send_out->depth = fd_mcache_depth( ctx->send_out->mcache ); - ctx->send_out->seq = fd_mcache_seq_query( ctx->send_out->sync ); - } else { - FD_LOG_ERR(( "unrecognized out link `%s`", out_link->name )); - } - } + /* Net RX links (tango output links from net tile POV) */ - /* Check if any of the tiles we set a listen port for do not have an outlink. */ - if( FD_UNLIKELY( ctx->shred_listen_port!=0 && ctx->shred_out->mcache==NULL ) ) { - FD_LOG_ERR(( "shred listen port set but no out link was found" )); - } else if( FD_UNLIKELY( ctx->quic_transaction_listen_port!=0 && ctx->quic_out->mcache==NULL ) ) { - FD_LOG_ERR(( "quic transaction listen port set but no out link was found" )); - } else if( FD_UNLIKELY( ctx->legacy_transaction_listen_port!=0 && ctx->quic_out->mcache==NULL ) ) { - FD_LOG_ERR(( "legacy transaction listen port set but no out link was found" )); - } else if( FD_UNLIKELY( ctx->gossip_listen_port!=0 && ctx->gossip_out->mcache==NULL ) ) { - FD_LOG_ERR(( "gossip listen port set but no out link was found" )); - } else if( FD_UNLIKELY( ctx->repair_intake_listen_port!=0 && ctx->repair_out->mcache==NULL ) ) { - FD_LOG_ERR(( "repair intake port set but no out link was found" )); - } else if( FD_UNLIKELY( ctx->repair_serve_listen_port!=0 && ctx->repair_out->mcache==NULL ) ) { - FD_LOG_ERR(( "repair serve listen port set but no out link was found" )); - } else if( FD_UNLIKELY( ctx->neigh4_solicit->mcache==NULL ) ) { - FD_LOG_ERR(( "netlink request link not found" )); - } else if( FD_UNLIKELY( ctx->send_src_port!=0 && ctx->send_out->mcache==NULL ) ) { - FD_LOG_ERR(( "send listen port set but no out link was found" )); + fd_topo_net_rx_t const * rx_cfg = &tile->net.rx_rules; + ctx->rx_port_cnt = (uint)( rx_cfg->rx_rule_cnt ); + for( ulong i=0uL; i<(rx_cfg->rx_rule_cnt); i++ ) { + char const * link_name = rx_cfg->rx_rules[ i ].link; + uint out_link_idx = setup_out_link( ctx, topo, tile, link_name, ctx->net_tile_id ); + ctx->rx_port_keys.h[ i ] = rx_cfg->rx_rules[ i ].port; + ctx->rx_port_vals [ i ].out_link_idx = (uchar)out_link_idx; + ctx->rx_port_vals [ i ].dst_proto = (uchar)rx_cfg->rx_rules[ i ].proto_id; } + /* XDP flush timing objects */ + for( uint j=0U; j<2U; j++ ) { ctx->tx_flusher[ j ].pending_wmark = (ulong)( (double)tile->xdp.xdp_tx_queue_size * 0.7 ); ctx->tx_flusher[ j ].tail_flush_backoff = (long)( (double)tile->xdp.tx_flush_timeout_ns * fd_tempo_tick_per_ns( NULL ) ); ctx->tx_flusher[ j ].next_tail_flush_ticks = LONG_MAX; } - /* Join netbase objects */ + /* Netlink tile shared memory objects */ + ctx->fib_local = fd_fib4_join( fd_topo_obj_laddr( topo, tile->xdp.fib4_local_obj_id ) ); ctx->fib_main = fd_fib4_join( fd_topo_obj_laddr( topo, tile->xdp.fib4_main_obj_id ) ); if( FD_UNLIKELY( !ctx->fib_local || !ctx->fib_main ) ) FD_LOG_ERR(( "fd_fib4_join failed" )); diff --git a/src/disco/net/xdp/test_xdp_tile.c b/src/disco/net/xdp/test_xdp_tile.c index 8b23c4e707..96df74ab1d 100644 --- a/src/disco/net/xdp/test_xdp_tile.c +++ b/src/disco/net/xdp/test_xdp_tile.c @@ -318,11 +318,17 @@ main( int argc, ctx->umem_wmark = (uint)umem_wmark; ctx->umem_sz = umem_sz; - ctx->shred_listen_port = SHRED_PORT; - ctx->shred_out->mcache = rx_link->mcache; - ctx->shred_out->sync = fd_mcache_seq_laddr( ctx->shred_out->mcache ); - ctx->shred_out->depth = fd_mcache_depth( ctx->shred_out->mcache ); - ctx->shred_out->seq = fd_mcache_seq_query( ctx->shred_out->sync ); + /* RX flow steer rule */ + uint rx_port_idx = ctx->rx_port_cnt++; + ctx->rx_port_keys.h[ rx_port_idx ] = SHRED_PORT; + ctx->rx_port_vals [ rx_port_idx ].dst_proto = DST_PROTO_SHRED; + ctx->rx_port_vals [ rx_port_idx ].out_link_idx = 0; + + /* RX out link */ + ctx->out[ 0 ].mcache = rx_link->mcache; + ctx->out[ 0 ].sync = fd_mcache_seq_laddr( rx_link->mcache ); + ctx->out[ 0 ].depth = fd_mcache_depth ( rx_link->mcache ); + ctx->out[ 0 ].seq = 0UL; /* Initialize out link mcache chunks (RX links) */ ulong frame_off = 0UL; @@ -423,7 +429,7 @@ main( int argc, ulong cr_avail = ULONG_MAX; fd_stem_context_t stem[1] = {{ .mcaches = &rx_link->mcache, - .seqs = &ctx->shred_out->seq, + .seqs = &ctx->out[ 0 ].seq, .depths = &link_depth, .cr_avail = &cr_avail, .cr_decrement_amount = 0UL diff --git a/src/disco/shred/fd_shred_tile.c b/src/disco/shred/fd_shred_tile.c index b991dfca18..45ce24aed4 100644 --- a/src/disco/shred/fd_shred_tile.c +++ b/src/disco/shred/fd_shred_tile.c @@ -1,4 +1,4 @@ -#include "../tiles.h" +#include "fd_shred_tile.h" #include "generated/fd_shred_tile_seccomp.h" #include "../../util/pod/fd_pod_format.h" @@ -172,6 +172,7 @@ typedef struct { ushort net_id; int skip_frag; + int ping_frag; ulong adtl_dests_leader_cnt; fd_shred_dest_weighted_t adtl_dests_leader [ FD_TOPO_ADTL_DESTS_MAX ]; @@ -349,6 +350,64 @@ before_frag( fd_shred_ctx_t * ctx, return 0; } +/* *** Ping forwarding *** + Solana peers use a simple 'ping-pong' to do a primitive form of + address and endpoint validation. (Mainly defeats reflection-like + flood attacks, by allowing receivers to decline flows) + + Unfortunately, ping-pong flows that belong to the repair tile reuse + the 'repair intake' port, which ends up at the shred tile. So, the + shred tile must forward pings back to repair. */ + +static int +forward_ping_prepare( + fd_shred_ctx_t * ctx, + uchar const * buf, + ulong sz +) { + /* Don't do anything if the repair tile doesn't exist in this topology */ + if( FD_UNLIKELY( !ctx->repair_out_mem ) ) return 0; + + /* Extract IPv4 and UDP info, so downstream can generate a response */ + if( FD_UNLIKELY( szrepair link. + Pings are smaller than the shred_repair MTU, so we always have + space to send a frame. */ + FD_STATIC_ASSERT( FD_SHRED_REPAIR_MTU>=sizeof(fd_repair_ping_fwd_t), mtu ); + fd_repair_ping_fwd_t * dst = fd_chunk_to_laddr( ctx->repair_out_mem, ctx->repair_out_chunk ); + dst->src_ip4 = ip4.saddr; + dst->src_port = fd_ushort_bswap( udp.net_sport ); + fd_memcpy( dst->ping, buf, FD_REPAIR_PING_SZ ); + return 1; +} + +static void +forward_ping_commit( + fd_shred_ctx_t * ctx, + fd_stem_context_t * stem +) { + /* Don't do anything if the repair tile doesn't exist in this topology */ + if( FD_UNLIKELY( !ctx->repair_out_mem ) ) return; + + /* Commit a previous shred->repair ping forward */ + ulong out_idx = ctx->repair_out_idx; + ulong sig = ULONG_MAX; /* repair ping */ + ulong chunk = ctx->repair_out_chunk; + ulong sz = sizeof(fd_repair_ping_fwd_t); + ulong ctl = 0UL; /* unused */ + ulong tsorig = 0UL; /* TODO forward tsorig from upstream packet */ + ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() ); + fd_stem_publish( stem, out_idx, sig, chunk, sz, ctl, tsorig, tspub ); + + /* Wind up for next iteration */ + ctx->repair_out_chunk = fd_dcache_compact_next( chunk, sz, ctx->repair_out_chunk0, ctx->repair_out_wmark ); +} + static void during_frag( fd_shred_ctx_t * ctx, ulong in_idx, @@ -635,6 +694,16 @@ during_frag( fd_shred_ctx_t * ctx, uchar const * dcache_entry = fd_net_rx_translate_frag( &ctx->in[ in_idx ].net_rx, chunk, ctl, sz ); ulong hdr_sz = fd_disco_netmux_sig_hdr_sz( sig ); FD_TEST( hdr_sz <= sz ); /* Should be ensured by the net tile */ + + /* Ping traffic generated by the repair tile can end up with the + shred tile ~ forward it. */ + if( FD_UNLIKELY( (sz-hdr_sz)==FD_REPAIR_PING_SZ ) ) { + ctx->ping_frag = !!forward_ping_prepare( ctx, dcache_entry, sz ); + return; + } else { + ctx->ping_frag = 0; + } + fd_shred_t const * shred = fd_shred_parse( dcache_entry+hdr_sz, sz-hdr_sz ); if( FD_UNLIKELY( !shred ) ) { ctx->skip_frag = 1; @@ -808,6 +877,11 @@ after_frag( fd_shred_ctx_t * ctx, ulong fanout = 200UL; /* Default Agave's DATA_PLANE_FANOUT = 200UL */ if( FD_LIKELY( ctx->in_kind[ in_idx ]==IN_KIND_NET ) ) { + if( FD_UNLIKELY( ctx->ping_frag ) ) { + forward_ping_commit( ctx, stem ); + return; + } + uchar * shred_buffer = ctx->shred_buffer; ulong shred_buffer_sz = ctx->shred_buffer_sz; diff --git a/src/disco/shred/fd_shred_tile.h b/src/disco/shred/fd_shred_tile.h index a8b472c315..1fd3b7534d 100644 --- a/src/disco/shred/fd_shred_tile.h +++ b/src/disco/shred/fd_shred_tile.h @@ -4,12 +4,30 @@ #include "../tiles.h" #include "../../flamenco/types/fd_types_custom.h" +/* FD_REPAIR_PING_SZ is the UDP payload size of a 'ping'-related packet. + These incoming packets are forwarded to the repair tile. */ +#define FD_REPAIR_PING_SZ (132UL) + +struct fd_repair_ping_fwd { + uint src_ip4; + uint dst_ip4; + ushort src_port; + + /* FIXME: Just have a wire-format struct here for the ping frame. + This is currently not possible due to use of fd_types, which is not + guaranteed to have the same in-memory format as the wire format. */ + uchar ping[ FD_REPAIR_PING_SZ ]; +}; + +typedef struct fd_repair_ping_fwd fd_repair_ping_fwd_t; + /* Forward declarations */ typedef struct fd_fec_resolver fd_fec_resolver_t; typedef struct fd_keyswitch_private fd_keyswitch_t; typedef struct fd_keyguard_client fd_keyguard_client_t; -/* Shred tile context structure */ +/* Part of the shred tile context struct + FIXME remove this and just use fd_shred_ctx_t everywhere */ typedef struct { fd_shredder_t * shredder; fd_fec_resolver_t * resolver; @@ -27,6 +45,6 @@ typedef struct { fd_keyswitch_t * keyswitch; fd_keyguard_client_t keyguard_client[1]; /* ... rest of the structure members ... */ -} fd_shred_ctx_t; +} fd_shred_ctx_hdr_t; #endif /* HEADER_fd_src_disco_shred_fd_shred_tile_h */ diff --git a/src/disco/topo/fd_topo.h b/src/disco/topo/fd_topo.h index d6c446f83e..5ce1fb7bbe 100644 --- a/src/disco/topo/fd_topo.h +++ b/src/disco/topo/fd_topo.h @@ -29,13 +29,16 @@ /* Maximum number of additional destinations for leader shreds and for retransmitted shreds */ #define FD_TOPO_ADTL_DESTS_MAX ( 32UL) +#define FD_TOPO_LINK_NAME_SZ (13UL) + +#define FD_TOPO_NET_RX_RULE_MAX (32UL) /* A workspace is a Firedancer specific memory management structure that sits on top of 1 or more memory mapped gigantic or huge pages mounted to the hugetlbfs. */ typedef struct { 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. */ - char name[ 13UL ]; /* The name of this workspace, like "pack". There can be at most one of each workspace name in a topology. */ + char name[ FD_TOPO_LINK_NAME_SZ ]; /* The name of this workspace, like "pack". There can be at most one of each workspace name in a topology. */ ulong numa_idx; /* The index of the NUMA node on the system that this workspace should be allocated from. */ @@ -90,17 +93,53 @@ typedef struct { ushort port; /* in host byte order */ } fd_topo_ip_port_t; +struct fd_topo_net_rx_rule { + ushort port; + ushort proto_id; + char link[ FD_TOPO_LINK_NAME_SZ ]; +}; +typedef struct fd_topo_net_rx_rule fd_topo_net_rx_rule_t; + +struct fd_topo_net_rx { + fd_topo_net_rx_rule_t rx_rules[ FD_TOPO_NET_RX_RULE_MAX ]; + ushort rx_rule_cnt; +}; +typedef struct fd_topo_net_rx fd_topo_net_rx_t; + +static inline void +fd_topo_net_rx_rule_push( fd_topo_net_rx_t * net, + ushort dst_id, + char const * link_name, + ushort port ) { + ulong const prev_rule_cnt = net->rx_rule_cnt; + if( FD_UNLIKELY( prev_rule_cnt>=FD_TOPO_NET_RX_RULE_MAX ) ) { + FD_LOG_ERR(( "too many net rx rules" )); + } + + for( ulong i=0UL; irx_rules[ i ].port==port ) { + FD_LOG_ERR(( "duplicate net rx rule for port %hu", port )); + } + } + + fd_topo_net_rx_rule_t * rule = &net->rx_rules[ prev_rule_cnt ]; + fd_memset( rule, 0, sizeof(fd_topo_net_rx_rule_t) ); + rule->port = port; + rule->proto_id = dst_id; + + ulong link_name_len = strnlen( link_name, FD_TOPO_LINK_NAME_SZ ); + if( FD_UNLIKELY( link_name_len>=FD_TOPO_LINK_NAME_SZ ) ) { + FD_LOG_ERR(( "link name too long: \"%s\"", link_name )); + } + fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( rule->link ), link_name, link_name_len ) ); + + net->rx_rule_cnt = (ushort)( prev_rule_cnt+1UL ); +} + struct fd_topo_net_tile { ulong umem_dcache_obj_id; /* dcache for XDP UMEM frames */ uint bind_address; - - ushort shred_listen_port; - ushort quic_transaction_listen_port; - ushort legacy_transaction_listen_port; - ushort gossip_listen_port; - ushort repair_intake_listen_port; - ushort repair_serve_listen_port; - ushort send_src_port; + fd_topo_net_rx_t rx_rules; }; typedef struct fd_topo_net_tile fd_topo_net_tile_t; diff --git a/src/disco/topo/fd_topo_run.c b/src/disco/topo/fd_topo_run.c index 4fcacd4325..209d9e9ef3 100644 --- a/src/disco/topo/fd_topo_run.c +++ b/src/disco/topo/fd_topo_run.c @@ -252,22 +252,18 @@ fd_topo_install_xdp( fd_topo_t const * topo, FD_TEST( net0_tile_idx!=ULONG_MAX ); fd_topo_tile_t const * net0_tile = &topo->tiles[ net0_tile_idx ]; - ushort udp_port_candidates[] = { - (ushort)net0_tile->xdp.net.legacy_transaction_listen_port, - (ushort)net0_tile->xdp.net.quic_transaction_listen_port, - (ushort)net0_tile->xdp.net.shred_listen_port, - (ushort)net0_tile->xdp.net.gossip_listen_port, - (ushort)net0_tile->xdp.net.repair_intake_listen_port, - (ushort)net0_tile->xdp.net.repair_serve_listen_port, - (ushort)net0_tile->xdp.net.send_src_port, - }; + ulong const rule_cnt = net0_tile->net.rx_rules.rx_rule_cnt; + ushort udp_port_candidates[ FD_TOPO_NET_RX_RULE_MAX ]; + for( ulong i=0UL; inet.rx_rules.rx_rules[ i ].port; + } uint if_idx = if_nametoindex( net0_tile->xdp.interface ); if( FD_UNLIKELY( !if_idx ) ) FD_LOG_ERR(( "if_nametoindex(%s) failed", net0_tile->xdp.interface )); fd_xdp_fds_t xdp_fds = fd_xdp_install( if_idx, bind_addr, - sizeof(udp_port_candidates)/sizeof(udp_port_candidates[0]), + rule_cnt, udp_port_candidates, net0_tile->xdp.xdp_mode ); if( FD_UNLIKELY( -1==dup2( xdp_fds.xsk_map_fd, 123462 ) ) ) FD_LOG_ERR(( "dup2() failed (%i-%s)", errno, fd_io_strerror( errno ) )); diff --git a/src/discof/repair/fd_repair_tile.c b/src/discof/repair/fd_repair_tile.c index 206cb252aa..21abf79695 100644 --- a/src/discof/repair/fd_repair_tile.c +++ b/src/discof/repair/fd_repair_tile.c @@ -2,6 +2,7 @@ #define _GNU_SOURCE #include "../../disco/topo/fd_topo.h" +#include "../../disco/shred/fd_shred_tile.h" #include "generated/fd_repair_tile_seccomp.h" #include "../../flamenco/repair/fd_repair.h" @@ -253,14 +254,12 @@ handle_new_cluster_contact_info( fd_repair_tile_ctx_t * ctx, } } -ulong -fd_repair_handle_ping( fd_repair_tile_ctx_t * repair_tile_ctx, - fd_repair_t * glob, - fd_gossip_ping_t const * ping, - fd_gossip_peer_addr_t const * peer_addr FD_PARAM_UNUSED, - uint self_ip4_addr FD_PARAM_UNUSED, - uchar * msg_buf, - ulong msg_buf_sz ) { +static ulong +fd_repair_handle_ping( fd_repair_tile_ctx_t * repair_tile_ctx, + fd_repair_t * glob, + fd_gossip_ping_t const * ping, + uchar * msg_buf, + ulong msg_buf_sz ) { fd_repair_protocol_t protocol; fd_repair_protocol_new_disc(&protocol, fd_repair_protocol_enum_pong); fd_gossip_ping_t * pong = &protocol.inner.pong; @@ -286,8 +285,22 @@ fd_repair_handle_ping( fd_repair_tile_ctx_t * repair_tile_ctx, return buflen; } +static void +fd_repair_handle_ping1( fd_repair_tile_ctx_t * repair_tile_ctx, + fd_repair_t * glob, + fd_stem_context_t * stem, + fd_gossip_ping_t const * ping, + uint const src_ip, + uint const dst_port, + ushort const src_port ) { + uchar buf[1024]; + ulong buflen = fd_repair_handle_ping( repair_tile_ctx, glob, ping, buf, sizeof(buf) ); + ulong tsorig = fd_frag_meta_ts_comp( fd_tickcount() ); + send_packet( repair_tile_ctx, stem, 1, src_ip, src_port, dst_port, buf, buflen, tsorig ); +} + /* Pass a raw client response packet into the protocol. addr is the address of the sender */ -static int +static void fd_repair_recv_clnt_packet( fd_repair_tile_ctx_t * repair_tile_ctx, fd_stem_context_t * stem, fd_repair_t * glob, @@ -297,35 +310,25 @@ fd_repair_recv_clnt_packet( fd_repair_tile_ctx_t * repair_tile_ctx, uint dst_ip4_addr ) { glob->metrics.recv_clnt_pkt++; - FD_SCRATCH_SCOPE_BEGIN { - while( 1 ) { - ulong decoded_sz; - fd_repair_response_t * gmsg = fd_bincode_decode1_scratch( - repair_response, msg, msglen, NULL, &decoded_sz ); - if( FD_UNLIKELY( !gmsg ) ) { - /* Solana falls back to assuming we got a shred in this case - https://github.com/solana-labs/solana/blob/master/core/src/repair/serve_repair.rs#L1198 */ - break; - } - if( FD_UNLIKELY( decoded_sz != msglen ) ) { - break; - } - - switch( gmsg->discriminant ) { - case fd_repair_response_enum_ping: - { - uchar buf[1024]; - ulong buflen = fd_repair_handle_ping( repair_tile_ctx, glob, &gmsg->inner.ping, src_addr, dst_ip4_addr, buf, sizeof(buf) ); - ulong tsorig = fd_frag_meta_ts_comp( fd_tickcount() ); - send_packet( repair_tile_ctx, stem, 1, src_addr->addr, src_addr->port, dst_ip4_addr, buf, buflen, tsorig ); - break; - } - } - - return 0; + if( FD_UNLIKELY( msglenmetrics.recv_pkt_corrupted_msg++; + return; + } + uint msg_type = FD_LOAD( uint, msg ); + msg += sizeof(uint); + msglen -= sizeof(uint); + + switch( msg_type ) { + case 0: /* ping */ + if( FD_UNLIKELY( msglen!=132 ) ) { + glob->metrics.recv_pkt_corrupted_msg++; + return; } - } FD_SCRATCH_SCOPE_END; - return 0; + fd_repair_handle_ping1( repair_tile_ctx, glob, stem, fd_type_pun_const( msg ), src_addr->addr, dst_ip4_addr, src_addr->port ); + break; + default: + break; + } } static ulong @@ -427,7 +430,10 @@ before_frag( fd_repair_tile_ctx_t * ctx, ulong sig ) { uint in_kind = ctx->in_kind[ in_idx ]; if( FD_LIKELY ( in_kind==IN_KIND_NET ) ) return fd_disco_netmux_sig_proto( sig )!=DST_PROTO_REPAIR; - if( FD_UNLIKELY( in_kind==IN_KIND_SHRED ) ) return fd_int_if( fd_forest_root_slot( ctx->forest )==ULONG_MAX, -1, 0 ); /* not ready to read frag */ + if( FD_UNLIKELY( in_kind==IN_KIND_SHRED ) ) { + if( FD_UNLIKELY( sig==ULONG_MAX ) ) return 0; /* repair ping */ + return fd_int_if( fd_forest_root_slot( ctx->forest )==ULONG_MAX, -1, 0 ); /* not ready to read frag */ + } return 0; } @@ -646,6 +652,13 @@ after_frag( fd_repair_tile_ctx_t * ctx, return; } + if( FD_UNLIKELY( in_kind==IN_KIND_NET && sig==ULONG_MAX ) ) { + fd_repair_ping_fwd_t const * fwd = fd_type_pun_const( ctx->buffer ); + fd_gossip_ping_t const * ping = fd_type_pun_const( fwd->ping ); + fd_repair_handle_ping1( ctx, ctx->repair, stem, ping, fwd->src_ip4, fwd->dst_ip4, fwd->src_port ); + return; + } + fd_eth_hdr_t const * eth = (fd_eth_hdr_t const *)ctx->buffer; fd_ip4_hdr_t const * ip4 = (fd_ip4_hdr_t const *)( (ulong)eth + sizeof(fd_eth_hdr_t) ); fd_udp_hdr_t const * udp = (fd_udp_hdr_t const *)( (ulong)ip4 + FD_IP4_GET_LEN( *ip4 ) ); diff --git a/src/flamenco/types/fd_fuzz_types.h b/src/flamenco/types/fd_fuzz_types.h index 0bd02308a7..91f7a206ca 100644 --- a/src/flamenco/types/fd_fuzz_types.h +++ b/src/flamenco/types/fd_fuzz_types.h @@ -3675,23 +3675,6 @@ void *fd_repair_protocol_generate( void *mem, void **alloc_mem, fd_rng_t * rng ) return mem; } -void fd_repair_response_inner_generate( fd_repair_response_inner_t * self, void **alloc_mem, uint discriminant, fd_rng_t * rng ) { - switch (discriminant) { - case 0: { - fd_gossip_ping_generate( &self->ping, alloc_mem, rng ); - break; - } - } -} -void *fd_repair_response_generate( void *mem, void **alloc_mem, fd_rng_t * rng ) { - fd_repair_response_t *self = (fd_repair_response_t *) mem; - *alloc_mem = (uchar *) *alloc_mem + sizeof(fd_repair_response_t); - fd_repair_response_new(mem); - self->discriminant = fd_rng_uint( rng ) % 1; - fd_repair_response_inner_generate( &self->inner, alloc_mem, self->discriminant, rng ); - return mem; -} - void fd_instr_error_enum_inner_generate( fd_instr_error_enum_inner_t * self, void **alloc_mem, uint discriminant, fd_rng_t * rng ) { switch (discriminant) { case 25: { diff --git a/src/flamenco/types/fd_types.c b/src/flamenco/types/fd_types.c index cab99c49e8..8311185fa4 100644 --- a/src/flamenco/types/fd_types.c +++ b/src/flamenco/types/fd_types.c @@ -22410,116 +22410,6 @@ int fd_repair_protocol_encode( fd_repair_protocol_t const * self, fd_bincode_enc return fd_repair_protocol_inner_encode( &self->inner, self->discriminant, ctx ); } -FD_FN_PURE uchar fd_repair_response_is_ping(fd_repair_response_t const * self) { - return self->discriminant == 0; -} -void fd_repair_response_inner_new( fd_repair_response_inner_t * self, uint discriminant ); -int fd_repair_response_inner_decode_footprint( uint discriminant, fd_bincode_decode_ctx_t * ctx, ulong * total_sz ) { - int err; - switch (discriminant) { - case 0: { - err = fd_gossip_ping_decode_footprint_inner( ctx, total_sz ); - if( FD_UNLIKELY( err ) ) return err; - return FD_BINCODE_SUCCESS; - } - default: return FD_BINCODE_ERR_ENCODING; - } -} -static int fd_repair_response_decode_footprint_inner( fd_bincode_decode_ctx_t * ctx, ulong * total_sz ) { - if( ctx->data>=ctx->dataend ) { return FD_BINCODE_ERR_OVERFLOW; }; - uint discriminant = 0; - int err = fd_bincode_uint32_decode( &discriminant, ctx ); - if( FD_UNLIKELY( err ) ) return err; - return fd_repair_response_inner_decode_footprint( discriminant, ctx, total_sz ); -} -int fd_repair_response_decode_footprint( fd_bincode_decode_ctx_t * ctx, ulong * total_sz ) { - *total_sz += sizeof(fd_repair_response_t); - void const * start_data = ctx->data; - int err = fd_repair_response_decode_footprint_inner( ctx, total_sz ); - if( ctx->data>ctx->dataend ) { return FD_BINCODE_ERR_OVERFLOW; }; - ctx->data = start_data; - return err; -} -static void fd_repair_response_inner_decode_inner( fd_repair_response_inner_t * self, void * * alloc_mem, uint discriminant, fd_bincode_decode_ctx_t * ctx ) { - switch (discriminant) { - case 0: { - fd_gossip_ping_decode_inner( &self->ping, alloc_mem, ctx ); - break; - } - } -} -static void fd_repair_response_decode_inner( void * struct_mem, void * * alloc_mem, fd_bincode_decode_ctx_t * ctx ) { - fd_repair_response_t * self = (fd_repair_response_t *)struct_mem; - fd_bincode_uint32_decode_unsafe( &self->discriminant, ctx ); - fd_repair_response_inner_decode_inner( &self->inner, alloc_mem, self->discriminant, ctx ); -} -void * fd_repair_response_decode( void * mem, fd_bincode_decode_ctx_t * ctx ) { - fd_repair_response_t * self = (fd_repair_response_t *)mem; - fd_repair_response_new( self ); - void * alloc_region = (uchar *)mem + sizeof(fd_repair_response_t); - void * * alloc_mem = &alloc_region; - fd_repair_response_decode_inner( mem, alloc_mem, ctx ); - return self; -} -void fd_repair_response_inner_new( fd_repair_response_inner_t * self, uint discriminant ) { - switch( discriminant ) { - case 0: { - fd_gossip_ping_new( &self->ping ); - break; - } - default: break; // FD_LOG_ERR(( "unhandled type")); - } -} -void fd_repair_response_new_disc( fd_repair_response_t * self, uint discriminant ) { - self->discriminant = discriminant; - fd_repair_response_inner_new( &self->inner, self->discriminant ); -} -void fd_repair_response_new( fd_repair_response_t * self ) { - fd_memset( self, 0, sizeof(fd_repair_response_t) ); - fd_repair_response_new_disc( self, UINT_MAX ); -} - -void fd_repair_response_walk( void * w, fd_repair_response_t const * self, fd_types_walk_fn_t fun, const char *name, uint level, uint varint ) { - (void) varint; - fun(w, self, name, FD_FLAMENCO_TYPE_ENUM, "fd_repair_response", level++, 0); - switch( self->discriminant ) { - case 0: { - fun( w, self, "ping", FD_FLAMENCO_TYPE_ENUM_DISC, "discriminant", level, 0 ); - fd_gossip_ping_walk( w, &self->inner.ping, fun, "ping", level, 0 ); - break; - } - } - fun( w, self, name, FD_FLAMENCO_TYPE_ENUM_END, "fd_repair_response", level--, 0 ); -} -ulong fd_repair_response_size( fd_repair_response_t const * self ) { - ulong size = 0; - size += sizeof(uint); - switch (self->discriminant) { - case 0: { - size += fd_gossip_ping_size( &self->inner.ping ); - break; - } - } - return size; -} - -int fd_repair_response_inner_encode( fd_repair_response_inner_t const * self, uint discriminant, fd_bincode_encode_ctx_t * ctx ) { - int err; - switch (discriminant) { - case 0: { - err = fd_gossip_ping_encode( &self->ping, ctx ); - if( FD_UNLIKELY( err ) ) return err; - break; - } - } - return FD_BINCODE_SUCCESS; -} -int fd_repair_response_encode( fd_repair_response_t const * self, fd_bincode_encode_ctx_t * ctx ) { - int err = fd_bincode_uint32_encode( self->discriminant, ctx ); - if( FD_UNLIKELY( err ) ) return err; - return fd_repair_response_inner_encode( &self->inner, self->discriminant, ctx ); -} - FD_FN_PURE uchar fd_instr_error_enum_is_generic_error(fd_instr_error_enum_t const * self) { return self->discriminant == 0; } diff --git a/src/flamenco/types/fd_types.h b/src/flamenco/types/fd_types.h index 51275c8bfe..01c9bb384b 100644 --- a/src/flamenco/types/fd_types.h +++ b/src/flamenco/types/fd_types.h @@ -3266,18 +3266,6 @@ struct fd_repair_protocol { typedef struct fd_repair_protocol fd_repair_protocol_t; #define FD_REPAIR_PROTOCOL_ALIGN alignof(fd_repair_protocol_t) -union fd_repair_response_inner { - fd_gossip_ping_t ping; -}; -typedef union fd_repair_response_inner fd_repair_response_inner_t; - -struct fd_repair_response { - uint discriminant; - fd_repair_response_inner_t inner; -}; -typedef struct fd_repair_response fd_repair_response_t; -#define FD_REPAIR_RESPONSE_ALIGN alignof(fd_repair_response_t) - union fd_instr_error_enum_inner { uint custom; char* borsh_io_error; @@ -6115,19 +6103,6 @@ fd_repair_protocol_enum_highest_window_index = 9, fd_repair_protocol_enum_orphan = 10, fd_repair_protocol_enum_ancestor_hashes = 11, }; -void fd_repair_response_new_disc( fd_repair_response_t * self, uint discriminant ); -void fd_repair_response_new( fd_repair_response_t * self ); -int fd_repair_response_encode( fd_repair_response_t const * self, fd_bincode_encode_ctx_t * ctx ); -void fd_repair_response_walk( void * w, fd_repair_response_t const * self, fd_types_walk_fn_t fun, const char *name, uint level, uint varint ); -ulong fd_repair_response_size( fd_repair_response_t const * self ); -static inline ulong fd_repair_response_align( void ) { return FD_REPAIR_RESPONSE_ALIGN; } -int fd_repair_response_decode_footprint( fd_bincode_decode_ctx_t * ctx, ulong * total_sz ); -void * fd_repair_response_decode( void * mem, fd_bincode_decode_ctx_t * ctx ); - -FD_FN_PURE uchar fd_repair_response_is_ping( fd_repair_response_t const * self ); -enum { -fd_repair_response_enum_ping = 0, -}; void fd_instr_error_enum_new_disc( fd_instr_error_enum_t * self, uint discriminant ); void fd_instr_error_enum_new( fd_instr_error_enum_t * self ); int fd_instr_error_enum_encode( fd_instr_error_enum_t const * self, fd_bincode_encode_ctx_t * ctx ); diff --git a/src/flamenco/types/fd_types.json b/src/flamenco/types/fd_types.json index ff5210d0fe..f5fd5c6e30 100644 --- a/src/flamenco/types/fd_types.json +++ b/src/flamenco/types/fd_types.json @@ -2302,13 +2302,6 @@ { "name": "ancestor_hashes", "type": "repair_ancestor_hashes" } ] }, - { - "name": "repair_response", - "type": "enum", - "variants": [ - { "name": "ping", "type": "gossip_ping" } - ] - }, { "name": "instr_error_enum", "type": "enum", diff --git a/src/flamenco/types/fd_types_reflect_generated.c b/src/flamenco/types/fd_types_reflect_generated.c index d9f7d6cb6f..ab9187f75c 100644 --- a/src/flamenco/types/fd_types_reflect_generated.c +++ b/src/flamenco/types/fd_types_reflect_generated.c @@ -3,7 +3,7 @@ #include "fd_types_custom.h" #include "fd_types_reflect_private.h" #pragma GCC diagnostic ignored "-Wpedantic" -ulong fd_types_vt_list_cnt = 248; +ulong fd_types_vt_list_cnt = 247; fd_types_vt_t const fd_types_vt_list[] = { { .name="fd_hash", .name_len=7, .align=FD_HASH_ALIGN, .new_=(void *)fd_hash_new, .decode=(void *)fd_hash_decode, .size=(void *)fd_hash_size, .walk=(void *)fd_hash_walk, .decode_footprint=(void *)fd_hash_decode_footprint, .encode=(void *)fd_hash_encode }, { .name="fd_pubkey", .name_len=9, .align=FD_PUBKEY_ALIGN, .new_=(void *)fd_pubkey_new, .decode=(void *)fd_pubkey_decode, .size=(void *)fd_pubkey_size, .walk=(void *)fd_pubkey_walk, .decode_footprint=(void *)fd_pubkey_decode_footprint, .encode=(void *)fd_pubkey_encode }, @@ -228,7 +228,6 @@ fd_types_vt_t const fd_types_vt_list[] = { { .name="fd_repair_orphan", .name_len=16, .align=FD_REPAIR_ORPHAN_ALIGN, .new_=(void *)fd_repair_orphan_new, .decode=(void *)fd_repair_orphan_decode, .size=(void *)fd_repair_orphan_size, .walk=(void *)fd_repair_orphan_walk, .decode_footprint=(void *)fd_repair_orphan_decode_footprint, .encode=(void *)fd_repair_orphan_encode }, { .name="fd_repair_ancestor_hashes", .name_len=25, .align=FD_REPAIR_ANCESTOR_HASHES_ALIGN, .new_=(void *)fd_repair_ancestor_hashes_new, .decode=(void *)fd_repair_ancestor_hashes_decode, .size=(void *)fd_repair_ancestor_hashes_size, .walk=(void *)fd_repair_ancestor_hashes_walk, .decode_footprint=(void *)fd_repair_ancestor_hashes_decode_footprint, .encode=(void *)fd_repair_ancestor_hashes_encode }, { .name="fd_repair_protocol", .name_len=18, .align=FD_REPAIR_PROTOCOL_ALIGN, .new_=(void *)fd_repair_protocol_new, .decode=(void *)fd_repair_protocol_decode, .size=(void *)fd_repair_protocol_size, .walk=(void *)fd_repair_protocol_walk, .decode_footprint=(void *)fd_repair_protocol_decode_footprint, .encode=(void *)fd_repair_protocol_encode }, - { .name="fd_repair_response", .name_len=18, .align=FD_REPAIR_RESPONSE_ALIGN, .new_=(void *)fd_repair_response_new, .decode=(void *)fd_repair_response_decode, .size=(void *)fd_repair_response_size, .walk=(void *)fd_repair_response_walk, .decode_footprint=(void *)fd_repair_response_decode_footprint, .encode=(void *)fd_repair_response_encode }, { .name="fd_instr_error_enum", .name_len=19, .align=FD_INSTR_ERROR_ENUM_ALIGN, .new_=(void *)fd_instr_error_enum_new, .decode=(void *)fd_instr_error_enum_decode, .size=(void *)fd_instr_error_enum_size, .walk=(void *)fd_instr_error_enum_walk, .decode_footprint=(void *)fd_instr_error_enum_decode_footprint, .encode=(void *)fd_instr_error_enum_encode }, { .name="fd_txn_instr_error", .name_len=18, .align=FD_TXN_INSTR_ERROR_ALIGN, .new_=(void *)fd_txn_instr_error_new, .decode=(void *)fd_txn_instr_error_decode, .size=(void *)fd_txn_instr_error_size, .walk=(void *)fd_txn_instr_error_walk, .decode_footprint=(void *)fd_txn_instr_error_decode_footprint, .encode=(void *)fd_txn_instr_error_encode }, { .name="fd_txn_error_enum", .name_len=17, .align=FD_TXN_ERROR_ENUM_ALIGN, .new_=(void *)fd_txn_error_enum_new, .decode=(void *)fd_txn_error_enum_decode, .size=(void *)fd_txn_error_enum_size, .walk=(void *)fd_txn_error_enum_walk, .decode_footprint=(void *)fd_txn_error_enum_decode_footprint, .encode=(void *)fd_txn_error_enum_encode },