use std::time::Duration;
use nlink::netlink::{
Connection, KobjectUevent, Route, RtnetlinkGroup,
netdev::{NetdevEvent, NetdevInfo, NetdevLifecycle},
reflector::Store,
uevent_filter::UeventFilter,
};
use tokio_stream::StreamExt;
#[tokio::main]
async fn main() -> nlink::Result<()> {
let links = Connection::<Route>::new()?;
links.subscribe(&[RtnetlinkGroup::Link])?;
let uevents = Connection::<KobjectUevent>::new()?;
let compiled = uevents.attach_filter(&UeventFilter::new().subsystem("net").build())?;
println!(
"uevent prefilter: {} instructions, rcvbuf {} bytes",
compiled.len(),
uevents.rcvbuf()?
);
let store: Store<u32, NetdevInfo> = Store::new();
let mut lifecycle =
NetdevLifecycle::new(links.events().await, uevents.events().await).with_store(store.clone());
let reader = store.clone();
tokio::spawn(async move {
loop {
tokio::time::sleep(Duration::from_secs(5)).await;
let mut devices = reader.snapshot();
devices.sort_by_key(|(ifindex, _)| *ifindex);
println!("\n--- cache: {} devices ---", devices.len());
for (ifindex, info) in devices {
println!(
" {ifindex:>3} {:<16} driver={:<10} attributed={}",
info.name().unwrap_or("?"),
info.driver().unwrap_or("-"),
info.is_fully_attributed()
);
}
println!();
}
});
println!("watching netdev lifecycle; Ctrl+C to exit\n");
while let Some(event) = lifecycle.next().await {
match event? {
NetdevEvent::Added(info) => println!(
"ADDED {:>3} {} driver={:?} devpath={:?}",
info.ifindex(),
info.name().unwrap_or("?"),
info.driver(),
info.devpath(),
),
NetdevEvent::Changed(info) => println!(
"CHANGED {:>3} {} devtype={:?} devpath={:?} attributed={}",
info.ifindex(),
info.name().unwrap_or("?"),
info.devtype(),
info.devpath(),
info.is_fully_attributed(),
),
NetdevEvent::DriverBound { ifindex, annotation } => {
println!("BOUND {ifindex:>3} driver={:?}", annotation.driver)
}
NetdevEvent::DriverUnbound { ifindex, annotation } => {
println!("UNBOUND {ifindex:>3} driver={:?}", annotation.driver)
}
NetdevEvent::Removed { ifindex, name } => {
println!("REMOVED {ifindex:>3} {}", name.unwrap_or_default())
}
other => println!("{other:?}"),
}
}
Ok(())
}