2 Commits

Author SHA1 Message Date
Gilles Soulier 5ee8b66464 feat(v0.1.7): port iperf3 configurable + iperf3 docker sur port 5202
- config.toml: nouveau champ [server] iperf3_port (défaut 5201)
- network_info: iperf3 -p <port> utilise le port configuré
- docker-compose: iperf3 exposé sur 5202 (5201 occupé par linux_benchtools)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 06:47:15 +02:00
Gilles Soulier c238e9f2b8 fix: supprimer service iperf3 — port 5201 déjà occupé par linux_benchtools
Un container iperf3 (linux_benchtools_iperf3) tourne depuis 4 mois sur le
même hôte. L'agent se connecte à l'IP du serveur:5201 qui résout vers ce
container existant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 06:43:06 +02:00
7 changed files with 14 additions and 9 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nanometrics-agent" name = "nanometrics-agent"
version = "0.1.6" version = "0.1.7"
edition = "2021" edition = "2021"
[lib] [lib]
+4
View File
@@ -13,8 +13,12 @@ pub struct Config {
pub struct ServerConfig { pub struct ServerConfig {
pub ip: String, pub ip: String,
pub port: u16, pub port: u16,
#[serde(default = "default_iperf3_port")]
pub iperf3_port: u16,
} }
fn default_iperf3_port() -> u16 { 5201 }
#[derive(Deserialize, Debug, Clone, Default)] #[derive(Deserialize, Debug, Clone, Default)]
pub struct ProtocolsConfig { pub struct ProtocolsConfig {
#[serde(default)] #[serde(default)]
+2 -2
View File
@@ -86,7 +86,7 @@ fn main() {
let mut startup_net: Option<Vec<payload::NetworkInterface>> = None; let mut startup_net: Option<Vec<payload::NetworkInterface>> = None;
let mut startup_hw: Option<payload::HardwareInfo> = None; let mut startup_hw: Option<payload::HardwareInfo> = None;
if cfg.metrics.network_info.udp || cfg.metrics.network_info.mqtt { if cfg.metrics.network_info.udp || cfg.metrics.network_info.mqtt {
let ni = metrics::network_info::collect(&cfg.server.ip); let ni = metrics::network_info::collect(&cfg.server.ip, cfg.server.iperf3_port);
if !ni.is_empty() { startup_net = Some(ni); } if !ni.is_empty() { startup_net = Some(ni); }
} }
if cfg.metrics.hardware_info.udp || cfg.metrics.hardware_info.mqtt { if cfg.metrics.hardware_info.udp || cfg.metrics.hardware_info.mqtt {
@@ -116,7 +116,7 @@ fn main() {
if ch == slow_time.0 && cm == slow_time.1 { if ch == slow_time.0 && cm == slow_time.1 {
slow_daily_done = true; slow_daily_done = true;
if cfg.metrics.network_info.udp || cfg.metrics.network_info.mqtt { if cfg.metrics.network_info.udp || cfg.metrics.network_info.mqtt {
let ni = metrics::network_info::collect(&cfg.server.ip); let ni = metrics::network_info::collect(&cfg.server.ip, cfg.server.iperf3_port);
if !ni.is_empty() { daily_net = Some(ni); } if !ni.is_empty() { daily_net = Some(ni); }
} }
if cfg.metrics.hardware_info.udp || cfg.metrics.hardware_info.mqtt { if cfg.metrics.hardware_info.udp || cfg.metrics.hardware_info.mqtt {
+5 -4
View File
@@ -56,12 +56,13 @@ fn wol_status(name: &str) -> Option<bool> {
None None
} }
fn iperf_mbps(server_ip: &str) -> Option<f64> { fn iperf_mbps(server_ip: &str, port: u16) -> Option<f64> {
std::process::Command::new("which").arg("iperf3") std::process::Command::new("which").arg("iperf3")
.output().ok() .output().ok()
.filter(|o| o.status.success())?; .filter(|o| o.status.success())?;
let port_str = port.to_string();
let out = std::process::Command::new("iperf3") let out = std::process::Command::new("iperf3")
.args(["-c", server_ip, "-J", "-t", "5", "-P", "1"]) .args(["-c", server_ip, "-p", &port_str, "-J", "-t", "5", "-P", "1"])
.output().ok()?; .output().ok()?;
let json = String::from_utf8_lossy(&out.stdout); let json = String::from_utf8_lossy(&out.stdout);
let v: serde_json::Value = serde_json::from_str(&json).ok()?; let v: serde_json::Value = serde_json::from_str(&json).ok()?;
@@ -69,7 +70,7 @@ fn iperf_mbps(server_ip: &str) -> Option<f64> {
Some((bps / 1_000_000.0 * 10.0).round() / 10.0) Some((bps / 1_000_000.0 * 10.0).round() / 10.0)
} }
pub fn collect(server_ip: &str) -> Vec<crate::payload::NetworkInterface> { pub fn collect(server_ip: &str, iperf3_port: u16) -> Vec<crate::payload::NetworkInterface> {
let entries = match std::fs::read_dir("/sys/class/net") { let entries = match std::fs::read_dir("/sys/class/net") {
Ok(e) => e, Ok(e) => e,
Err(_) => return vec![], Err(_) => return vec![],
@@ -82,7 +83,7 @@ pub fn collect(server_ip: &str) -> Vec<crate::payload::NetworkInterface> {
ifaces.sort(); ifaces.sort();
if ifaces.is_empty() { return vec![]; } if ifaces.is_empty() { return vec![]; }
let iperf = iperf_mbps(server_ip); let iperf = iperf_mbps(server_ip, iperf3_port);
ifaces.iter().map(|name| { ifaces.iter().map(|name| {
let speed = read_sysfs(name, "speed") let speed = read_sysfs(name, "speed")
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -38,8 +38,8 @@ services:
restart: unless-stopped restart: unless-stopped
command: ["-s"] command: ["-s"]
ports: ports:
- "5201:5201/tcp" - "5202:5201/tcp"
- "5201:5201/udp" - "5202:5201/udp"
volumes: volumes:
nanometrics_data: nanometrics_data: