use nlink::netlink::{
Connection, Route,
diagnostics::{Diagnostics, DiagnosticsConfig, Severity},
};
#[tokio::main]
async fn main() -> nlink::Result<()> {
let conn = Connection::<Route>::new()?;
let diag = Diagnostics::new(conn);
println!("=== Network Diagnostics Scan ===\n");
let report = diag.scan().await?;
println!("Scan completed at {:?}\n", report.timestamp);
println!("--- Interfaces ({}) ---\n", report.interfaces.len());
for iface in &report.interfaces {
print!("{}: ", iface.name);
if iface.up {
print!("UP ");
} else {
print!("DOWN ");
}
if iface.carrier {
print!("CARRIER ");
}
if let Some(mtu) = iface.mtu {
print!("mtu {} ", mtu);
}
println!();
if let Some(stats) = &iface.stats {
println!(
" RX: {} packets, {} bytes",
stats.rx_packets, stats.rx_bytes
);
println!(
" TX: {} packets, {} bytes",
stats.tx_packets, stats.tx_bytes
);
if stats.rx_errors > 0 || stats.tx_errors > 0 {
println!(" Errors: RX {} TX {}", stats.rx_errors, stats.tx_errors);
}
if stats.rx_dropped > 0 || stats.tx_dropped > 0 {
println!(" Dropped: RX {} TX {}", stats.rx_dropped, stats.tx_dropped);
}
}
if let Some(rates) = &iface.rates {
if rates.total_bps() > 0 {
println!(
" Rate: {:.2} Mbps ({:.0} pps)",
rates.total_bps() as f64 / 1_000_000.0,
rates.total_pps()
);
}
}
if let Some(tc) = &iface.tc {
print!(" TC: {} qdisc", tc.qdisc);
if tc.drops > 0 {
print!(", {} drops", tc.drops);
}
if tc.overlimits > 0 {
print!(", {} overlimits", tc.overlimits);
}
println!();
}
if !iface.issues.is_empty() {
for issue in &iface.issues {
let severity_str = match issue.severity {
Severity::Critical => "CRITICAL",
Severity::Error => "ERROR",
Severity::Warning => "WARN",
Severity::Info => "INFO",
};
println!(" [{}] {}: {}", severity_str, issue.category, issue.message);
}
}
println!();
}
println!("--- Routes ---\n");
println!(" IPv4 routes: {}", report.routes.ipv4_route_count);
println!(" IPv6 routes: {}", report.routes.ipv6_route_count);
println!(
" Default IPv4: {}",
if report.routes.has_default_v4 {
"yes"
} else {
"no"
}
);
println!(
" Default IPv6: {}",
if report.routes.has_default_v6 {
"yes"
} else {
"no"
}
);
if !report.routes.gateways.is_empty() {
println!(" Gateways: {:?}", report.routes.gateways);
}
println!();
if !report.issues.is_empty() {
println!("--- Issues Found ({}) ---\n", report.issues.len());
for issue in &report.issues {
let severity_str = match issue.severity {
Severity::Critical => "CRITICAL",
Severity::Error => "ERROR",
Severity::Warning => "WARN",
Severity::Info => "INFO",
};
print!("[{}] {}", severity_str, issue.message);
if let Some(iface) = &issue.interface {
print!(" ({})", iface);
}
println!();
if let Some(details) = &issue.details {
println!(" {}", details);
}
}
} else {
println!("No issues detected.");
}
Ok(())
}