-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding configurabele TCP buffers and minor hafixes #4649
Changes from all commits
780a276
88bfa1e
08b00c6
5d0025e
495e74f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,10 @@ pub const MAX_MESSAGE_SIZE: usize = 64 * 1024 * 1024; /* 64 MiB */ | |
pub const CONNECTION_BACKOFF_BASE: u64 = 2; | ||
pub const IP_BYTE_BUCKET_RATE: usize = 102400 /* 100 KiB */; | ||
pub const IP_BYTE_BUCKET_SIZE: usize = IP_BYTE_BUCKET_RATE; | ||
pub const INBOUND_TCP_RX_BUFFER_SIZE: u32 = 3 * 1024 * 1024; // 3MB ~6MB/s with 500ms latency | ||
pub const INBOUND_TCP_TX_BUFFER_SIZE: u32 = 512 * 1024; // 1MB use a bigger spoon | ||
pub const OUTBOUND_TCP_RX_BUFFER_SIZE: u32 = 3 * 1024 * 1024; // 3MB ~6MB/s with 500ms latency | ||
pub const OUTBOUND_TCP_TX_BUFFER_SIZE: u32 = 1024 * 1024; // 1MB use a bigger spoon | ||
|
||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] | ||
#[serde(default, deny_unknown_fields)] | ||
|
@@ -79,6 +83,10 @@ pub struct NetworkConfig { | |
pub mutual_authentication: bool, | ||
pub network_id: NetworkId, | ||
pub runtime_threads: Option<usize>, | ||
pub inbound_rx_buffer_size_bytes: Option<u32>, | ||
pub inbound_tx_buffer_size_bytes: Option<u32>, | ||
pub outbound_rx_buffer_size_bytes: Option<u32>, | ||
pub outbound_tx_buffer_size_bytes: Option<u32>, | ||
Comment on lines
+86
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I heard There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No it should be fine, so long as this lands: #4847 |
||
// Addresses of initial peers to connect to. In a mutual_authentication network, | ||
// we will extract the public keys from these addresses to set our initial | ||
// trusted peers set. TODO: Replace usage in configs with `seeds` this is for backwards compatibility | ||
|
@@ -141,6 +149,10 @@ impl NetworkConfig { | |
inbound_rate_limit_config: None, | ||
outbound_rate_limit_config: None, | ||
max_message_size: MAX_MESSAGE_SIZE, | ||
inbound_rx_buffer_size_bytes: Some(INBOUND_TCP_RX_BUFFER_SIZE), | ||
inbound_tx_buffer_size_bytes: Some(INBOUND_TCP_TX_BUFFER_SIZE), | ||
outbound_rx_buffer_size_bytes: Some(OUTBOUND_TCP_RX_BUFFER_SIZE), | ||
outbound_tx_buffer_size_bytes: Some(OUTBOUND_TCP_TX_BUFFER_SIZE), | ||
}; | ||
config.prepare_identity(); | ||
config | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,6 @@ use futures::{ | |
}; | ||
use proxy::Proxy; | ||
use std::{ | ||
convert::TryFrom, | ||
fmt::Debug, | ||
io, | ||
net::SocketAddr, | ||
|
@@ -29,13 +28,47 @@ use tokio::{ | |
use tokio_util::compat::Compat; | ||
use url::Url; | ||
|
||
#[derive(Debug, Clone, Copy, Default)] | ||
pub struct TCPBufferCfg { | ||
inbound_rx_buffer_bytes: Option<u32>, | ||
inbound_tx_buffer_bytes: Option<u32>, | ||
outbound_rx_buffer_bytes: Option<u32>, | ||
outbound_tx_buffer_bytes: Option<u32>, | ||
} | ||
|
||
impl TCPBufferCfg { | ||
pub const fn new() -> Self { | ||
Self { | ||
inbound_rx_buffer_bytes: None, | ||
inbound_tx_buffer_bytes: None, | ||
outbound_rx_buffer_bytes: None, | ||
outbound_tx_buffer_bytes: None, | ||
} | ||
} | ||
pub fn new_configs( | ||
inbound_rx: Option<u32>, | ||
inbound_tx: Option<u32>, | ||
outbound_rx: Option<u32>, | ||
outbound_tx: Option<u32>, | ||
) -> Self { | ||
Self { | ||
inbound_rx_buffer_bytes: inbound_rx, | ||
inbound_tx_buffer_bytes: inbound_tx, | ||
outbound_rx_buffer_bytes: outbound_rx, | ||
outbound_tx_buffer_bytes: outbound_tx, | ||
} | ||
} | ||
} | ||
|
||
/// Transport to build TCP connections | ||
#[derive(Debug, Clone, Default)] | ||
pub struct TcpTransport { | ||
/// TTL to set for opened sockets, or `None` to keep default. | ||
pub ttl: Option<u32>, | ||
/// `TCP_NODELAY` to set for opened sockets, or `None` to keep default. | ||
pub nodelay: Option<bool>, | ||
|
||
pub tcp_buff_cfg: TCPBufferCfg, | ||
} | ||
|
||
impl TcpTransport { | ||
|
@@ -50,6 +83,10 @@ impl TcpTransport { | |
|
||
Ok(()) | ||
} | ||
|
||
pub fn set_tcp_buffers(&mut self, configs: &TCPBufferCfg) { | ||
self.tcp_buff_cfg = *configs; | ||
} | ||
} | ||
|
||
impl Transport for TcpTransport { | ||
|
@@ -69,9 +106,23 @@ impl Transport for TcpTransport { | |
return Err(invalid_addr_error(&addr)); | ||
} | ||
|
||
let listener = ::std::net::TcpListener::bind((ipaddr, port))?; | ||
listener.set_nonblocking(true)?; | ||
let listener = TcpListener::try_from(listener)?; | ||
let addr = SocketAddr::new(ipaddr, port); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did we change this to not set_nonblocking? |
||
let socket = if ipaddr.is_ipv4() { | ||
tokio::net::TcpSocket::new_v4()? | ||
} else { | ||
tokio::net::TcpSocket::new_v6()? | ||
}; | ||
|
||
if let Some(rx_buf) = self.tcp_buff_cfg.inbound_rx_buffer_bytes { | ||
socket.set_recv_buffer_size(rx_buf)?; | ||
} | ||
if let Some(tx_buf) = self.tcp_buff_cfg.inbound_tx_buffer_bytes { | ||
socket.set_send_buffer_size(tx_buf)?; | ||
} | ||
socket.bind(addr)?; | ||
|
||
let listener = socket.listen(256)?; | ||
let listen_addr = NetworkAddress::from(listener.local_addr()?); | ||
|
||
Ok(( | ||
|
@@ -88,7 +139,6 @@ impl Transport for TcpTransport { | |
|
||
// ensure addr is well formed to save some work before potentially | ||
// spawning a dial task that will fail anyway. | ||
// TODO(philiphayes): base tcp transport should not allow trailing protocols | ||
parse_ip_tcp(protos) | ||
.map(|_| ()) | ||
.or_else(|| parse_dns_tcp(protos).map(|_| ())) | ||
|
@@ -123,7 +173,7 @@ impl Transport for TcpTransport { | |
let f: Pin<Box<dyn Future<Output = io::Result<TcpStream>> + Send + 'static>> = | ||
Box::pin(match proxy_addr { | ||
Some(proxy_addr) => Either::Left(connect_via_proxy(proxy_addr, addr)), | ||
None => Either::Right(resolve_and_connect(addr)), | ||
None => Either::Right(resolve_and_connect(addr, self.tcp_buff_cfg)), | ||
}); | ||
|
||
Ok(TcpOutbound { | ||
|
@@ -144,23 +194,48 @@ async fn resolve_with_filter( | |
.filter(move |socketaddr| ip_filter.matches(socketaddr.ip()))) | ||
} | ||
|
||
pub async fn connect_with_config( | ||
port: u16, | ||
ipaddr: std::net::IpAddr, | ||
tcp_buff_cfg: TCPBufferCfg, | ||
) -> io::Result<TcpStream> { | ||
let addr = SocketAddr::new(ipaddr, port); | ||
|
||
let socket = if addr.is_ipv4() { | ||
tokio::net::TcpSocket::new_v4()? | ||
} else { | ||
tokio::net::TcpSocket::new_v6()? | ||
}; | ||
|
||
if let Some(rx_buf) = tcp_buff_cfg.outbound_rx_buffer_bytes { | ||
socket.set_recv_buffer_size(rx_buf)?; | ||
} | ||
if let Some(tx_buf) = tcp_buff_cfg.outbound_tx_buffer_bytes { | ||
socket.set_send_buffer_size(tx_buf)?; | ||
} | ||
socket.connect(addr).await | ||
} | ||
|
||
/// Note: we need to take ownership of this `NetworkAddress` (instead of just | ||
/// borrowing the `&[Protocol]` slice) so this future can be `Send + 'static`. | ||
pub async fn resolve_and_connect(addr: NetworkAddress) -> io::Result<TcpStream> { | ||
pub async fn resolve_and_connect( | ||
addr: NetworkAddress, | ||
tcp_buff_cfg: TCPBufferCfg, | ||
) -> io::Result<TcpStream> { | ||
let protos = addr.as_slice(); | ||
|
||
if let Some(((ipaddr, port), _addr_suffix)) = parse_ip_tcp(protos) { | ||
// this is an /ip4 or /ip6 address, so we can just connect without any | ||
// extra resolving or filtering. | ||
TcpStream::connect((ipaddr, port)).await | ||
connect_with_config(port, ipaddr, tcp_buff_cfg).await | ||
} else if let Some(((ip_filter, dns_name, port), _addr_suffix)) = parse_dns_tcp(protos) { | ||
// resolve dns name and filter | ||
let socketaddr_iter = resolve_with_filter(ip_filter, dns_name.as_ref(), port).await?; | ||
let mut last_err = None; | ||
|
||
// try to connect until the first succeeds | ||
for socketaddr in socketaddr_iter { | ||
match TcpStream::connect(socketaddr).await { | ||
match connect_with_config(socketaddr.port(), socketaddr.ip(), tcp_buff_cfg).await { | ||
Ok(stream) => return Ok(stream), | ||
Err(err) => last_err = Some(err), | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a technical term, or just informal wording?
use a bigger spoon
😄 Not sure how to respond based on the comment lolThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Informal but descriptive.