diff --git a/neard/src/cli.rs b/neard/src/cli.rs index ed84d245dd7..4012544db47 100644 --- a/neard/src/cli.rs +++ b/neard/src/cli.rs @@ -459,6 +459,7 @@ impl RunCmd { .unwrap_or_else(|e| panic!("Error loading config: {:#}", e)); check_release_build(&near_config.client_config.chain_id); + check_kernel_params(); // Set current version in client config. near_config.client_config.version = crate::neard_version(); @@ -808,6 +809,62 @@ impl ValidateConfigCommand { } } +#[cfg(target_os = "linux")] +fn normalize_whitespace(s: &str) -> String { + s.split_whitespace().collect::>().join(" ") +} + +/// Checks the provided kernel parameter from /proc/sys +/// and prints an error if it is not set to the expected value. +#[cfg(target_os = "linux")] +fn check_kernel_param(param_name: &str, expected_value: &str) { + // Convert the dotted param_name into a path under /proc/sys + // For example, "net.core.rmem_max" -> "/proc/sys/net/core/rmem_max" + let mut path = PathBuf::from("/proc/sys"); + for part in param_name.split('.') { + path.push(part); + } + + match std::fs::read_to_string(&path) { + Ok(contents) => { + let actual = contents.trim(); + let actual_normalized = normalize_whitespace(actual); + let expected_normalized = normalize_whitespace(expected_value); + + if actual_normalized != expected_normalized { + error!( + "ERROR: {} is set to {}, expected {}. Please run `scripts/set_kernel_params.sh`.", + param_name, actual_normalized, expected_normalized + ); + } else { + info!("OK: {} is set to expected value {}", param_name, expected_normalized); + } + } + Err(e) => { + error!("ERROR: failed to read parameter {} from {}: {}", param_name, path.display(), e); + } + } +} + +#[cfg(not(target_os = "linux"))] +fn check_kernel_params() {} + +/// Checks if the system has the expected values for the sysctl parameters for optimal networking performance. +#[cfg(target_os = "linux")] +fn check_kernel_params() { + let expected_rmem_max = "8388608"; + let expected_wmem_max = "8388608"; + let expected_tcp_rmem = "4096 87380 8388608"; + let expected_tcp_wmem = "4096 16384 8388608"; + let expected_slow_start = "0"; + + check_kernel_param("net.core.rmem_max", expected_rmem_max); + check_kernel_param("net.core.wmem_max", expected_wmem_max); + check_kernel_param("net.ipv4.tcp_rmem", expected_tcp_rmem); + check_kernel_param("net.ipv4.tcp_wmem", expected_tcp_wmem); + check_kernel_param("net.ipv4.tcp_slow_start_after_idle", expected_slow_start); +} + #[cfg(test)] mod tests { use super::{CryptoHash, NeardCmd, NeardSubCommand, VerifyProofError, VerifyProofSubCommand}; diff --git a/scripts/set_kernel_params.sh b/scripts/set_kernel_params.sh new file mode 100644 index 00000000000..f6b6944278d --- /dev/null +++ b/scripts/set_kernel_params.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# This script sets specific sysctl parameters for running a validator. +# Run it as: sudo ./set_kernel_params.sh + +# Increase maximum read and write buffer sizes +sysctl -w net.core.rmem_max=8388608 +sysctl -w net.core.wmem_max=8388608 + +# Configure TCP read and write memory parameters +sysctl -w net.ipv4.tcp_rmem="4096 87380 8388608" +sysctl -w net.ipv4.tcp_wmem="4096 16384 8388608" + +# Disable slow start after idle +sysctl -w net.ipv4.tcp_slow_start_after_idle=0 + +echo "Network settings have been updated."