Add fullnode --dynamic-port-range option
This commit is contained in:
@ -31,11 +31,12 @@ use rand::{thread_rng, Rng};
|
||||
use rayon::prelude::*;
|
||||
use solana_metrics::counter::Counter;
|
||||
use solana_metrics::{influxdb, submit};
|
||||
use solana_netutil::{bind_in_range, bind_to, find_available_port_in_range, multi_bind_in_range};
|
||||
use solana_netutil::{
|
||||
bind_in_range, bind_to, find_available_port_in_range, multi_bind_in_range, PortRange,
|
||||
};
|
||||
use solana_runtime::bloom::Bloom;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::rpc_port;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signable, Signature};
|
||||
use solana_sdk::timing::{duration_as_ms, timestamp};
|
||||
use solana_sdk::transaction::Transaction;
|
||||
@ -48,7 +49,7 @@ use std::sync::{Arc, RwLock};
|
||||
use std::thread::{sleep, Builder, JoinHandle};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub const FULLNODE_PORT_RANGE: (u16, u16) = (8000, 10_000);
|
||||
pub const FULLNODE_PORT_RANGE: PortRange = (8000, 10_000);
|
||||
|
||||
/// The fanout for Ledger Replication
|
||||
pub const DATA_PLANE_FANOUT: usize = 200;
|
||||
@ -1510,7 +1511,7 @@ impl Node {
|
||||
},
|
||||
}
|
||||
}
|
||||
fn get_gossip_port(gossip_addr: &SocketAddr) -> (u16, UdpSocket) {
|
||||
fn get_gossip_port(gossip_addr: &SocketAddr, port_range: PortRange) -> (u16, UdpSocket) {
|
||||
if gossip_addr.port() != 0 {
|
||||
(
|
||||
gossip_addr.port(),
|
||||
@ -1519,27 +1520,29 @@ impl Node {
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
Self::bind()
|
||||
Self::bind(port_range)
|
||||
}
|
||||
}
|
||||
fn bind() -> (u16, UdpSocket) {
|
||||
bind_in_range(FULLNODE_PORT_RANGE).expect("Failed to bind")
|
||||
fn bind(port_range: PortRange) -> (u16, UdpSocket) {
|
||||
bind_in_range(port_range).expect("Failed to bind")
|
||||
}
|
||||
pub fn new_with_external_ip(pubkey: &Pubkey, gossip_addr: &SocketAddr) -> Node {
|
||||
let (gossip_port, gossip) = Self::get_gossip_port(gossip_addr);
|
||||
pub fn new_with_external_ip(
|
||||
pubkey: &Pubkey,
|
||||
gossip_addr: &SocketAddr,
|
||||
port_range: PortRange,
|
||||
) -> Node {
|
||||
let (gossip_port, gossip) = Self::get_gossip_port(gossip_addr, port_range);
|
||||
|
||||
let (tvu_port, tvu_sockets) =
|
||||
multi_bind_in_range(FULLNODE_PORT_RANGE, 8).expect("tvu multi_bind");
|
||||
let (tvu_port, tvu_sockets) = multi_bind_in_range(port_range, 8).expect("tvu multi_bind");
|
||||
|
||||
let (tpu_port, tpu_sockets) =
|
||||
multi_bind_in_range(FULLNODE_PORT_RANGE, 32).expect("tpu multi_bind");
|
||||
let (tpu_port, tpu_sockets) = multi_bind_in_range(port_range, 32).expect("tpu multi_bind");
|
||||
|
||||
let (tpu_via_blobs_port, tpu_via_blobs_sockets) =
|
||||
multi_bind_in_range(FULLNODE_PORT_RANGE, 8).expect("tpu multi_bind");
|
||||
multi_bind_in_range(port_range, 8).expect("tpu multi_bind");
|
||||
|
||||
let (_, repair) = Self::bind();
|
||||
let (_, broadcast) = Self::bind();
|
||||
let (_, retransmit) = Self::bind();
|
||||
let (_, repair) = Self::bind(port_range);
|
||||
let (_, broadcast) = Self::bind(port_range);
|
||||
let (_, retransmit) = Self::bind(port_range);
|
||||
|
||||
let info = ContactInfo::new(
|
||||
pubkey,
|
||||
@ -1547,9 +1550,9 @@ impl Node {
|
||||
SocketAddr::new(gossip_addr.ip(), tvu_port),
|
||||
SocketAddr::new(gossip_addr.ip(), tpu_port),
|
||||
SocketAddr::new(gossip_addr.ip(), tpu_via_blobs_port),
|
||||
"0.0.0.0:0".parse().unwrap(),
|
||||
SocketAddr::new(gossip_addr.ip(), rpc_port::DEFAULT_RPC_PORT),
|
||||
SocketAddr::new(gossip_addr.ip(), rpc_port::DEFAULT_RPC_PUBSUB_PORT),
|
||||
socketaddr_any!(),
|
||||
socketaddr_any!(),
|
||||
socketaddr_any!(),
|
||||
0,
|
||||
);
|
||||
trace!("new ContactInfo: {:?}", info);
|
||||
@ -1568,14 +1571,18 @@ impl Node {
|
||||
},
|
||||
}
|
||||
}
|
||||
pub fn new_replicator_with_external_ip(pubkey: &Pubkey, gossip_addr: &SocketAddr) -> Node {
|
||||
let mut new = Self::new_with_external_ip(pubkey, gossip_addr);
|
||||
let (storage_port, storage_socket) = Self::bind();
|
||||
pub fn new_replicator_with_external_ip(
|
||||
pubkey: &Pubkey,
|
||||
gossip_addr: &SocketAddr,
|
||||
port_range: PortRange,
|
||||
) -> Node {
|
||||
let mut new = Self::new_with_external_ip(pubkey, gossip_addr, port_range);
|
||||
let (storage_port, storage_socket) = Self::bind(port_range);
|
||||
|
||||
new.info.storage_addr = SocketAddr::new(gossip_addr.ip(), storage_port);
|
||||
new.sockets.storage = Some(storage_socket);
|
||||
|
||||
let empty = "0.0.0.0:0".parse().unwrap();
|
||||
let empty = socketaddr_any!();
|
||||
new.info.tpu = empty;
|
||||
new.info.tpu_via_blobs = empty;
|
||||
new.sockets.tpu = vec![];
|
||||
@ -1904,7 +1911,11 @@ mod tests {
|
||||
#[test]
|
||||
fn new_with_external_ip_test_random() {
|
||||
let ip = Ipv4Addr::from(0);
|
||||
let node = Node::new_with_external_ip(&Pubkey::new_rand(), &socketaddr!(ip, 0));
|
||||
let node = Node::new_with_external_ip(
|
||||
&Pubkey::new_rand(),
|
||||
&socketaddr!(ip, 0),
|
||||
FULLNODE_PORT_RANGE,
|
||||
);
|
||||
|
||||
check_node_sockets(&node, IpAddr::V4(ip), FULLNODE_PORT_RANGE);
|
||||
}
|
||||
@ -1917,7 +1928,11 @@ mod tests {
|
||||
.expect("Failed to bind")
|
||||
.0
|
||||
};
|
||||
let node = Node::new_with_external_ip(&Pubkey::new_rand(), &socketaddr!(0, port));
|
||||
let node = Node::new_with_external_ip(
|
||||
&Pubkey::new_rand(),
|
||||
&socketaddr!(0, port),
|
||||
FULLNODE_PORT_RANGE,
|
||||
);
|
||||
|
||||
check_node_sockets(&node, ip, FULLNODE_PORT_RANGE);
|
||||
|
||||
@ -1927,7 +1942,11 @@ mod tests {
|
||||
#[test]
|
||||
fn new_replicator_external_ip_test() {
|
||||
let ip = Ipv4Addr::from(0);
|
||||
let node = Node::new_replicator_with_external_ip(&Pubkey::new_rand(), &socketaddr!(ip, 0));
|
||||
let node = Node::new_replicator_with_external_ip(
|
||||
&Pubkey::new_rand(),
|
||||
&socketaddr!(ip, 0),
|
||||
FULLNODE_PORT_RANGE,
|
||||
);
|
||||
|
||||
let ip = IpAddr::V4(ip);
|
||||
check_socket(&node.sockets.storage.unwrap(), ip, FULLNODE_PORT_RANGE);
|
||||
|
@ -1,7 +1,10 @@
|
||||
use bincode::serialize;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
#[cfg(test)]
|
||||
use solana_sdk::rpc_port;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signable, Signature};
|
||||
#[cfg(test)]
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::signature::{Signable, Signature};
|
||||
use solana_sdk::timing::timestamp;
|
||||
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
@ -141,16 +144,19 @@ impl ContactInfo {
|
||||
0,
|
||||
)
|
||||
}
|
||||
fn next_port(addr: &SocketAddr, nxt: u16) -> SocketAddr {
|
||||
let mut nxt_addr = *addr;
|
||||
nxt_addr.set_port(addr.port() + nxt);
|
||||
nxt_addr
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn new_with_pubkey_socketaddr(pubkey: &Pubkey, bind_addr: &SocketAddr) -> Self {
|
||||
fn next_port(addr: &SocketAddr, nxt: u16) -> SocketAddr {
|
||||
let mut nxt_addr = *addr;
|
||||
nxt_addr.set_port(addr.port() + nxt);
|
||||
nxt_addr
|
||||
}
|
||||
|
||||
let tpu_addr = *bind_addr;
|
||||
let gossip_addr = Self::next_port(&bind_addr, 1);
|
||||
let tvu_addr = Self::next_port(&bind_addr, 2);
|
||||
let tpu_via_blobs_addr = Self::next_port(&bind_addr, 3);
|
||||
let gossip_addr = next_port(&bind_addr, 1);
|
||||
let tvu_addr = next_port(&bind_addr, 2);
|
||||
let tpu_via_blobs_addr = next_port(&bind_addr, 3);
|
||||
let rpc_addr = SocketAddr::new(bind_addr.ip(), rpc_port::DEFAULT_RPC_PORT);
|
||||
let rpc_pubsub_addr = SocketAddr::new(bind_addr.ip(), rpc_port::DEFAULT_RPC_PUBSUB_PORT);
|
||||
Self::new(
|
||||
@ -165,7 +171,9 @@ impl ContactInfo {
|
||||
timestamp(),
|
||||
)
|
||||
}
|
||||
pub fn new_with_socketaddr(bind_addr: &SocketAddr) -> Self {
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn new_with_socketaddr(bind_addr: &SocketAddr) -> Self {
|
||||
let keypair = Keypair::new();
|
||||
Self::new_with_pubkey_socketaddr(&keypair.pubkey(), bind_addr)
|
||||
}
|
||||
@ -185,11 +193,13 @@ impl ContactInfo {
|
||||
timestamp(),
|
||||
)
|
||||
}
|
||||
|
||||
fn is_valid_ip(addr: IpAddr) -> bool {
|
||||
!(addr.is_unspecified() || addr.is_multicast())
|
||||
// || (addr.is_loopback() && !cfg_test))
|
||||
// TODO: boot loopback in production networks
|
||||
}
|
||||
|
||||
/// port must not be 0
|
||||
/// ip must be specified and not mulitcast
|
||||
/// loopback ip is only allowed in tests
|
||||
|
@ -142,24 +142,32 @@ impl Fullnode {
|
||||
|
||||
let storage_state = StorageState::new();
|
||||
|
||||
let rpc_service = JsonRpcService::new(
|
||||
&cluster_info,
|
||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), node.info.rpc.port()),
|
||||
storage_state.clone(),
|
||||
config.rpc_config.clone(),
|
||||
bank_forks.clone(),
|
||||
&exit,
|
||||
);
|
||||
let rpc_service = if node.info.rpc.port() == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(JsonRpcService::new(
|
||||
&cluster_info,
|
||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), node.info.rpc.port()),
|
||||
storage_state.clone(),
|
||||
config.rpc_config.clone(),
|
||||
bank_forks.clone(),
|
||||
&exit,
|
||||
))
|
||||
};
|
||||
|
||||
let subscriptions = Arc::new(RpcSubscriptions::default());
|
||||
let rpc_pubsub_service = PubSubService::new(
|
||||
&subscriptions,
|
||||
SocketAddr::new(
|
||||
IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
|
||||
node.info.rpc_pubsub.port(),
|
||||
),
|
||||
&exit,
|
||||
);
|
||||
let rpc_pubsub_service = if node.info.rpc_pubsub.port() == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(PubSubService::new(
|
||||
&subscriptions,
|
||||
SocketAddr::new(
|
||||
IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
|
||||
node.info.rpc_pubsub.port(),
|
||||
),
|
||||
&exit,
|
||||
))
|
||||
};
|
||||
|
||||
let gossip_service = GossipService::new(
|
||||
&cluster_info,
|
||||
@ -243,8 +251,8 @@ impl Fullnode {
|
||||
Self {
|
||||
id,
|
||||
gossip_service,
|
||||
rpc_service: Some(rpc_service),
|
||||
rpc_pubsub_service: Some(rpc_pubsub_service),
|
||||
rpc_service,
|
||||
rpc_pubsub_service,
|
||||
tpu,
|
||||
tvu,
|
||||
exit,
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! The `local_vote_signer_service` can be started locally to sign fullnode votes
|
||||
|
||||
use crate::cluster_info::FULLNODE_PORT_RANGE;
|
||||
use crate::service::Service;
|
||||
use solana_netutil::PortRange;
|
||||
use solana_vote_signer::rpc::VoteSignerRpcService;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@ -24,8 +24,8 @@ impl Service for LocalVoteSignerService {
|
||||
|
||||
impl LocalVoteSignerService {
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
pub fn new() -> (Self, SocketAddr) {
|
||||
let addr = match solana_netutil::find_available_port_in_range(FULLNODE_PORT_RANGE) {
|
||||
pub fn new(port_range: PortRange) -> (Self, SocketAddr) {
|
||||
let addr = match solana_netutil::find_available_port_in_range(port_range) {
|
||||
Ok(port) => SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), port),
|
||||
Err(_e) => panic!("Failed to find an available port for local vote signer service"),
|
||||
};
|
||||
|
Reference in New Issue
Block a user