smolmix + sdk: throughput and latency tuning for the Goblin read tunnel
ci-binary-config-checker / publish-nym (arc-ubuntu-22.04) (push) Has been cancelled
ci-binary-config-checker / publish-nym (arc-ubuntu-22.04) (push) Has been cancelled
256KB TCP buffers (was 8KB) + burst 64 (was 1) in smolmix; an IpMixStream::from_client constructor + best_ipr helper and reply-SURBs 10->4 in the ipr wrapper so a caller can back the tunnel with a high-traffic-profile MixnetClient. No behavior change to the default connect_new path used by the scoped exit.
This commit is contained in:
@@ -53,22 +53,52 @@ impl IpMixStream {
|
||||
///
|
||||
/// Returns a ready-to-use tunnel with allocated IP addresses.
|
||||
pub async fn new() -> Result<Self, Error> {
|
||||
let ipr_address = Self::best_ipr().await?;
|
||||
Self::new_with_ipr(ipr_address).await
|
||||
}
|
||||
|
||||
/// Auto-discover the best available IPR exit for the mainnet.
|
||||
///
|
||||
/// Exposed so a caller that wants to back the tunnel with its own tuned
|
||||
/// [`MixnetClient`] (via [`IpMixStream::from_client`]) can still get the
|
||||
/// auto-selected exit that [`IpMixStream::new`] would have used.
|
||||
pub async fn best_ipr() -> Result<Recipient, Error> {
|
||||
let network_defaults = NymNetworkDetails::new_mainnet();
|
||||
let api_client =
|
||||
create_nym_api_client(network_defaults.nym_api_urls.ok_or(Error::NoNymAPIUrl)?)?;
|
||||
let ipr_address = get_best_ipr(api_client).await?;
|
||||
Self::new_with_ipr(ipr_address).await
|
||||
get_best_ipr(api_client).await
|
||||
}
|
||||
|
||||
/// Connect to a specific IPR address.
|
||||
///
|
||||
/// Use this when you already know the IPR `Recipient` address (e.g. for
|
||||
/// testing against a specific exit node). For automatic discovery, use
|
||||
/// [`IpMixStream::new`] instead.
|
||||
/// [`IpMixStream::new`] instead. Backs the tunnel with a default
|
||||
/// [`MixnetClient::connect_new`] client (full cover traffic, poisson per-hop
|
||||
/// delays); for a tuned client use [`IpMixStream::from_client`].
|
||||
pub async fn new_with_ipr(ipr_address: Recipient) -> Result<Self, Error> {
|
||||
nym_network_defaults::setup_env(None::<&str>);
|
||||
let mut client = MixnetClient::connect_new().await?;
|
||||
let mut stream = client.open_stream(ipr_address, Some(10)).await?;
|
||||
let client = MixnetClient::connect_new().await?;
|
||||
Self::from_client(client, ipr_address).await
|
||||
}
|
||||
|
||||
/// Establish the IP tunnel over a caller-provided, already-connected
|
||||
/// [`MixnetClient`].
|
||||
///
|
||||
/// This is the low-anonymity-tuning seam: the caller builds the client with
|
||||
/// whatever traffic/anonymity [`DebugConfig`](crate::mixnet::config) it wants
|
||||
/// (e.g. a higher-throughput / lower-cover-traffic preset for a public read
|
||||
/// tunnel) and passes it in. Everything after the client — the stream open,
|
||||
/// the IPR connect handshake and the allocated-IP bookkeeping — is identical
|
||||
/// to [`new_with_ipr`](Self::new_with_ipr).
|
||||
pub async fn from_client(
|
||||
mut client: MixnetClient,
|
||||
ipr_address: Recipient,
|
||||
) -> Result<Self, Error> {
|
||||
// 4 reply-SURBs per stream (was 10): the IPR replies steadily, so a
|
||||
// smaller SURB budget still keeps the return path fed while cutting the
|
||||
// per-write SURB overhead on this public read tunnel.
|
||||
let mut stream = client.open_stream(ipr_address, Some(4)).await?;
|
||||
|
||||
info!("Connecting to IP packet router at {ipr_address}");
|
||||
let allocated_ips = Self::connect_tunnel(&mut stream).await?;
|
||||
|
||||
@@ -141,6 +141,11 @@ pub use nym_network_defaults::NymContracts;
|
||||
/// println!("API: {:?}", network.endpoints);
|
||||
/// ```
|
||||
pub use nym_network_defaults::NymNetworkDetails;
|
||||
/// Export the network (mainnet by default) environment configuration. Callers
|
||||
/// that build a [`MixnetClient`](mixnet::MixnetClient) themselves (rather than
|
||||
/// via [`MixnetClient::connect_new`](mixnet::MixnetClient::connect_new)) should
|
||||
/// call this first, mirroring what the higher-level constructors do internally.
|
||||
pub use nym_network_defaults::setup_env;
|
||||
/// Validator/API endpoint configuration.
|
||||
pub use nym_network_defaults::ValidatorDetails;
|
||||
|
||||
|
||||
@@ -33,7 +33,11 @@ impl NymAsyncDevice {
|
||||
let mut capabilities = DeviceCapabilities::default();
|
||||
capabilities.medium = Medium::Ip;
|
||||
capabilities.max_transmission_unit = 1500;
|
||||
capabilities.max_burst_size = Some(1);
|
||||
// Let the reactor process up to 64 packets per poll loop instead of one.
|
||||
// max_burst_size = Some(1) serialized all I/O to a single packet per
|
||||
// reactor wake, which throttles throughput badly over the mixnet's long
|
||||
// RTT; 64 lets a burst drain in one pass.
|
||||
capabilities.max_burst_size = Some(64);
|
||||
|
||||
Self {
|
||||
rx,
|
||||
|
||||
@@ -217,11 +217,19 @@ impl Tunnel {
|
||||
// Configure smoltcp: raw IP mode (no Ethernet), /32 for the allocated IP,
|
||||
// default route via unspecified (the IPR does the actual routing).
|
||||
let iface_config = Config::new(HardwareAddress::Ip);
|
||||
let net_config = NetConfig::new(
|
||||
let mut net_config = NetConfig::new(
|
||||
iface_config,
|
||||
IpCidr::new(IpAddress::from(allocated_ips.ipv4), 32),
|
||||
vec![IpAddress::from(Ipv4Address::UNSPECIFIED)],
|
||||
);
|
||||
// Lift the per-socket TCP window from tokio-smoltcp's 8 KB default to
|
||||
// 256 KB. The mixnet RTT is large (5 hops + deliberate per-hop delay),
|
||||
// so an 8 KB window caps bulk throughput at ~8 KB per round trip; 256 KB
|
||||
// lets many segments stay in flight, which is what makes relay/NIP-11/
|
||||
// price reads fast. Only the two TCP buffers change — every other
|
||||
// `BufferSize` field keeps its default.
|
||||
net_config.buffer_size.tcp_rx_size = 262144;
|
||||
net_config.buffer_size.tcp_tx_size = 262144;
|
||||
|
||||
// Net::new spawns the smoltcp reactor as a background task. After this,
|
||||
// tcp_connect/udp_bind create sockets managed by that reactor.
|
||||
|
||||
Reference in New Issue
Block a user