|
@@ -54,8 +54,9 @@ use {
|
|
|
solana_ledger::shred::Shred,
|
|
solana_ledger::shred::Shred,
|
|
|
solana_measure::measure::Measure,
|
|
solana_measure::measure::Measure,
|
|
|
solana_net_utils::{
|
|
solana_net_utils::{
|
|
|
- bind_common, bind_common_in_range, bind_in_range, bind_two_in_range_with_offset,
|
|
|
|
|
- find_available_port_in_range, multi_bind_in_range, PortRange,
|
|
|
|
|
|
|
+ bind_common, bind_common_in_range, bind_in_range, bind_in_range_with_config,
|
|
|
|
|
+ bind_more_with_config, bind_two_in_range_with_offset_and_config,
|
|
|
|
|
+ find_available_port_in_range, multi_bind_in_range, PortRange, SocketConfig,
|
|
|
},
|
|
},
|
|
|
solana_perf::{
|
|
solana_perf::{
|
|
|
data_budget::DataBudget,
|
|
data_budget::DataBudget,
|
|
@@ -2891,8 +2892,8 @@ pub struct Sockets {
|
|
|
pub serve_repair: UdpSocket,
|
|
pub serve_repair: UdpSocket,
|
|
|
pub serve_repair_quic: UdpSocket,
|
|
pub serve_repair_quic: UdpSocket,
|
|
|
pub ancestor_hashes_requests: UdpSocket,
|
|
pub ancestor_hashes_requests: UdpSocket,
|
|
|
- pub tpu_quic: UdpSocket,
|
|
|
|
|
- pub tpu_forwards_quic: UdpSocket,
|
|
|
|
|
|
|
+ pub tpu_quic: Vec<UdpSocket>,
|
|
|
|
|
+ pub tpu_forwards_quic: Vec<UdpSocket>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub struct NodeConfig {
|
|
pub struct NodeConfig {
|
|
@@ -2905,6 +2906,9 @@ pub struct NodeConfig {
|
|
|
pub num_tvu_sockets: NonZeroUsize,
|
|
pub num_tvu_sockets: NonZeroUsize,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// This will be adjusted and parameterized in follow-on PRs.
|
|
|
|
|
+const QUIC_ENDPOINTS: usize = 1;
|
|
|
|
|
+
|
|
|
#[derive(Debug)]
|
|
#[derive(Debug)]
|
|
|
pub struct Node {
|
|
pub struct Node {
|
|
|
pub info: ContactInfo,
|
|
pub info: ContactInfo,
|
|
@@ -2922,15 +2926,35 @@ impl Node {
|
|
|
let unspecified_bind_addr = format!("{:?}:0", IpAddr::V4(Ipv4Addr::UNSPECIFIED));
|
|
let unspecified_bind_addr = format!("{:?}:0", IpAddr::V4(Ipv4Addr::UNSPECIFIED));
|
|
|
let port_range = (1024, 65535);
|
|
let port_range = (1024, 65535);
|
|
|
|
|
|
|
|
|
|
+ let udp_config = SocketConfig { reuseport: false };
|
|
|
|
|
+ let quic_config = SocketConfig { reuseport: true };
|
|
|
let ((_tpu_port, tpu), (_tpu_quic_port, tpu_quic)) =
|
|
let ((_tpu_port, tpu), (_tpu_quic_port, tpu_quic)) =
|
|
|
- bind_two_in_range_with_offset(localhost_ip_addr, port_range, QUIC_PORT_OFFSET).unwrap();
|
|
|
|
|
|
|
+ bind_two_in_range_with_offset_and_config(
|
|
|
|
|
+ localhost_ip_addr,
|
|
|
|
|
+ port_range,
|
|
|
|
|
+ QUIC_PORT_OFFSET,
|
|
|
|
|
+ udp_config.clone(),
|
|
|
|
|
+ quic_config.clone(),
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+ let tpu_quic =
|
|
|
|
|
+ bind_more_with_config(tpu_quic, QUIC_ENDPOINTS, quic_config.clone()).unwrap();
|
|
|
let (gossip_port, (gossip, ip_echo)) =
|
|
let (gossip_port, (gossip, ip_echo)) =
|
|
|
bind_common_in_range(localhost_ip_addr, port_range).unwrap();
|
|
bind_common_in_range(localhost_ip_addr, port_range).unwrap();
|
|
|
let gossip_addr = SocketAddr::new(localhost_ip_addr, gossip_port);
|
|
let gossip_addr = SocketAddr::new(localhost_ip_addr, gossip_port);
|
|
|
let tvu = UdpSocket::bind(&localhost_bind_addr).unwrap();
|
|
let tvu = UdpSocket::bind(&localhost_bind_addr).unwrap();
|
|
|
let tvu_quic = UdpSocket::bind(&localhost_bind_addr).unwrap();
|
|
let tvu_quic = UdpSocket::bind(&localhost_bind_addr).unwrap();
|
|
|
let ((_tpu_forwards_port, tpu_forwards), (_tpu_forwards_quic_port, tpu_forwards_quic)) =
|
|
let ((_tpu_forwards_port, tpu_forwards), (_tpu_forwards_quic_port, tpu_forwards_quic)) =
|
|
|
- bind_two_in_range_with_offset(localhost_ip_addr, port_range, QUIC_PORT_OFFSET).unwrap();
|
|
|
|
|
|
|
+ bind_two_in_range_with_offset_and_config(
|
|
|
|
|
+ localhost_ip_addr,
|
|
|
|
|
+ port_range,
|
|
|
|
|
+ QUIC_PORT_OFFSET,
|
|
|
|
|
+ udp_config,
|
|
|
|
|
+ quic_config.clone(),
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+ let tpu_forwards_quic =
|
|
|
|
|
+ bind_more_with_config(tpu_forwards_quic, QUIC_ENDPOINTS, quic_config).unwrap();
|
|
|
let tpu_vote = UdpSocket::bind(&localhost_bind_addr).unwrap();
|
|
let tpu_vote = UdpSocket::bind(&localhost_bind_addr).unwrap();
|
|
|
let repair = UdpSocket::bind(&localhost_bind_addr).unwrap();
|
|
let repair = UdpSocket::bind(&localhost_bind_addr).unwrap();
|
|
|
let rpc_port = find_available_port_in_range(localhost_ip_addr, port_range).unwrap();
|
|
let rpc_port = find_available_port_in_range(localhost_ip_addr, port_range).unwrap();
|
|
@@ -3008,7 +3032,7 @@ impl Node {
|
|
|
if gossip_addr.port() != 0 {
|
|
if gossip_addr.port() != 0 {
|
|
|
(
|
|
(
|
|
|
gossip_addr.port(),
|
|
gossip_addr.port(),
|
|
|
- bind_common(bind_ip_addr, gossip_addr.port(), false).unwrap_or_else(|e| {
|
|
|
|
|
|
|
+ bind_common(bind_ip_addr, gossip_addr.port()).unwrap_or_else(|e| {
|
|
|
panic!("gossip_addr bind_to port {}: {}", gossip_addr.port(), e)
|
|
panic!("gossip_addr bind_to port {}: {}", gossip_addr.port(), e)
|
|
|
}),
|
|
}),
|
|
|
)
|
|
)
|
|
@@ -3017,7 +3041,16 @@ impl Node {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
fn bind(bind_ip_addr: IpAddr, port_range: PortRange) -> (u16, UdpSocket) {
|
|
fn bind(bind_ip_addr: IpAddr, port_range: PortRange) -> (u16, UdpSocket) {
|
|
|
- bind_in_range(bind_ip_addr, port_range).expect("Failed to bind")
|
|
|
|
|
|
|
+ let config = SocketConfig { reuseport: false };
|
|
|
|
|
+ Self::bind_with_config(bind_ip_addr, port_range, config)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fn bind_with_config(
|
|
|
|
|
+ bind_ip_addr: IpAddr,
|
|
|
|
|
+ port_range: PortRange,
|
|
|
|
|
+ config: SocketConfig,
|
|
|
|
|
+ ) -> (u16, UdpSocket) {
|
|
|
|
|
+ bind_in_range_with_config(bind_ip_addr, port_range, config).expect("Failed to bind")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub fn new_single_bind(
|
|
pub fn new_single_bind(
|
|
@@ -3030,10 +3063,30 @@ impl Node {
|
|
|
Self::get_gossip_port(gossip_addr, port_range, bind_ip_addr);
|
|
Self::get_gossip_port(gossip_addr, port_range, bind_ip_addr);
|
|
|
let (tvu_port, tvu) = Self::bind(bind_ip_addr, port_range);
|
|
let (tvu_port, tvu) = Self::bind(bind_ip_addr, port_range);
|
|
|
let (tvu_quic_port, tvu_quic) = Self::bind(bind_ip_addr, port_range);
|
|
let (tvu_quic_port, tvu_quic) = Self::bind(bind_ip_addr, port_range);
|
|
|
|
|
+ let udp_config = SocketConfig { reuseport: false };
|
|
|
|
|
+ let quic_config = SocketConfig { reuseport: true };
|
|
|
let ((tpu_port, tpu), (_tpu_quic_port, tpu_quic)) =
|
|
let ((tpu_port, tpu), (_tpu_quic_port, tpu_quic)) =
|
|
|
- bind_two_in_range_with_offset(bind_ip_addr, port_range, QUIC_PORT_OFFSET).unwrap();
|
|
|
|
|
|
|
+ bind_two_in_range_with_offset_and_config(
|
|
|
|
|
+ bind_ip_addr,
|
|
|
|
|
+ port_range,
|
|
|
|
|
+ QUIC_PORT_OFFSET,
|
|
|
|
|
+ udp_config.clone(),
|
|
|
|
|
+ quic_config.clone(),
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+ let tpu_quic =
|
|
|
|
|
+ bind_more_with_config(tpu_quic, QUIC_ENDPOINTS, quic_config.clone()).unwrap();
|
|
|
let ((tpu_forwards_port, tpu_forwards), (_tpu_forwards_quic_port, tpu_forwards_quic)) =
|
|
let ((tpu_forwards_port, tpu_forwards), (_tpu_forwards_quic_port, tpu_forwards_quic)) =
|
|
|
- bind_two_in_range_with_offset(bind_ip_addr, port_range, QUIC_PORT_OFFSET).unwrap();
|
|
|
|
|
|
|
+ bind_two_in_range_with_offset_and_config(
|
|
|
|
|
+ bind_ip_addr,
|
|
|
|
|
+ port_range,
|
|
|
|
|
+ QUIC_PORT_OFFSET,
|
|
|
|
|
+ udp_config,
|
|
|
|
|
+ quic_config.clone(),
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+ let tpu_forwards_quic =
|
|
|
|
|
+ bind_more_with_config(tpu_forwards_quic, QUIC_ENDPOINTS, quic_config).unwrap();
|
|
|
let (tpu_vote_port, tpu_vote) = Self::bind(bind_ip_addr, port_range);
|
|
let (tpu_vote_port, tpu_vote) = Self::bind(bind_ip_addr, port_range);
|
|
|
let (_, retransmit_socket) = Self::bind(bind_ip_addr, port_range);
|
|
let (_, retransmit_socket) = Self::bind(bind_ip_addr, port_range);
|
|
|
let (_, repair) = Self::bind(bind_ip_addr, port_range);
|
|
let (_, repair) = Self::bind(bind_ip_addr, port_range);
|
|
@@ -3117,21 +3170,28 @@ impl Node {
|
|
|
let (tpu_port, tpu_sockets) =
|
|
let (tpu_port, tpu_sockets) =
|
|
|
multi_bind_in_range(bind_ip_addr, port_range, 32).expect("tpu multi_bind");
|
|
multi_bind_in_range(bind_ip_addr, port_range, 32).expect("tpu multi_bind");
|
|
|
|
|
|
|
|
- let (_tpu_port_quic, tpu_quic) = Self::bind(
|
|
|
|
|
|
|
+ let quic_config = SocketConfig { reuseport: true };
|
|
|
|
|
+ let (_tpu_port_quic, tpu_quic) = Self::bind_with_config(
|
|
|
bind_ip_addr,
|
|
bind_ip_addr,
|
|
|
(tpu_port + QUIC_PORT_OFFSET, tpu_port + QUIC_PORT_OFFSET + 1),
|
|
(tpu_port + QUIC_PORT_OFFSET, tpu_port + QUIC_PORT_OFFSET + 1),
|
|
|
|
|
+ quic_config.clone(),
|
|
|
);
|
|
);
|
|
|
|
|
+ let tpu_quic =
|
|
|
|
|
+ bind_more_with_config(tpu_quic, QUIC_ENDPOINTS, quic_config.clone()).unwrap();
|
|
|
|
|
|
|
|
let (tpu_forwards_port, tpu_forwards_sockets) =
|
|
let (tpu_forwards_port, tpu_forwards_sockets) =
|
|
|
multi_bind_in_range(bind_ip_addr, port_range, 8).expect("tpu_forwards multi_bind");
|
|
multi_bind_in_range(bind_ip_addr, port_range, 8).expect("tpu_forwards multi_bind");
|
|
|
|
|
|
|
|
- let (_tpu_forwards_port_quic, tpu_forwards_quic) = Self::bind(
|
|
|
|
|
|
|
+ let (_tpu_forwards_port_quic, tpu_forwards_quic) = Self::bind_with_config(
|
|
|
bind_ip_addr,
|
|
bind_ip_addr,
|
|
|
(
|
|
(
|
|
|
tpu_forwards_port + QUIC_PORT_OFFSET,
|
|
tpu_forwards_port + QUIC_PORT_OFFSET,
|
|
|
tpu_forwards_port + QUIC_PORT_OFFSET + 1,
|
|
tpu_forwards_port + QUIC_PORT_OFFSET + 1,
|
|
|
),
|
|
),
|
|
|
|
|
+ quic_config.clone(),
|
|
|
);
|
|
);
|
|
|
|
|
+ let tpu_forwards_quic =
|
|
|
|
|
+ bind_more_with_config(tpu_forwards_quic, QUIC_ENDPOINTS, quic_config.clone()).unwrap();
|
|
|
|
|
|
|
|
let (tpu_vote_port, tpu_vote_sockets) =
|
|
let (tpu_vote_port, tpu_vote_sockets) =
|
|
|
multi_bind_in_range(bind_ip_addr, port_range, 1).expect("tpu_vote multi_bind");
|
|
multi_bind_in_range(bind_ip_addr, port_range, 1).expect("tpu_vote multi_bind");
|
|
@@ -3338,7 +3398,6 @@ mod tests {
|
|
|
},
|
|
},
|
|
|
itertools::izip,
|
|
itertools::izip,
|
|
|
solana_ledger::shred::Shredder,
|
|
solana_ledger::shred::Shredder,
|
|
|
- solana_net_utils::MINIMUM_VALIDATOR_PORT_RANGE_WIDTH,
|
|
|
|
|
solana_sdk::signature::{Keypair, Signer},
|
|
solana_sdk::signature::{Keypair, Signer},
|
|
|
solana_vote_program::{vote_instruction, vote_state::Vote},
|
|
solana_vote_program::{vote_instruction, vote_state::Vote},
|
|
|
std::{
|
|
std::{
|
|
@@ -3771,10 +3830,8 @@ mod tests {
|
|
|
fn new_with_external_ip_test_gossip() {
|
|
fn new_with_external_ip_test_gossip() {
|
|
|
// Can't use VALIDATOR_PORT_RANGE because if this test runs in parallel with others, the
|
|
// Can't use VALIDATOR_PORT_RANGE because if this test runs in parallel with others, the
|
|
|
// port returned by `bind_in_range()` might be snatched up before `Node::new_with_external_ip()` runs
|
|
// port returned by `bind_in_range()` might be snatched up before `Node::new_with_external_ip()` runs
|
|
|
- let port_range = (
|
|
|
|
|
- VALIDATOR_PORT_RANGE.1 + MINIMUM_VALIDATOR_PORT_RANGE_WIDTH,
|
|
|
|
|
- VALIDATOR_PORT_RANGE.1 + (2 * MINIMUM_VALIDATOR_PORT_RANGE_WIDTH),
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ let (start, end) = VALIDATOR_PORT_RANGE;
|
|
|
|
|
+ let port_range = (end, end + (end - start));
|
|
|
let ip = IpAddr::V4(Ipv4Addr::LOCALHOST);
|
|
let ip = IpAddr::V4(Ipv4Addr::LOCALHOST);
|
|
|
let port = bind_in_range(ip, port_range).expect("Failed to bind").0;
|
|
let port = bind_in_range(ip, port_range).expect("Failed to bind").0;
|
|
|
let config = NodeConfig {
|
|
let config = NodeConfig {
|