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 },