Add tsunagi status over a local control socket
There was no way to ask a running agent what it was doing; the only status came from the periodic print of the `up` process itself. The new ipc module is an adapter over the public API: nothing in the agent core knows it exists, so a Windows named pipe or an authenticated loopback socket can be added beside it. It is also a different interface from the peer-to-peer protocol — between processes on one machine, authorised by filesystem permissions rather than the network secret. The socket is 0600 inside an owner-only directory, the wire format is length-prefixed postcard with the same bounds the network protocol uses, and the report types are their own stable format rather than the crate's internals. The socket path is derived from the state directory into XDG_RUNTIME_DIR when there is one. A Unix socket address is limited to about 100 bytes, and a deeply nested state directory overflows it — which is exactly what happened on the first attempt. Two presentation fixes while here. Multicast is counted separately from unroutable traffic, because Linux emits multicast on every IPv6 interface and it was showing up as "packets for unknown addresses" on a healthy agent. And WireGuard protocol errors are no longer added into the dropped counter: a few are normal while both ends start a handshake at once, and a working tunnel was reporting "dropped 3" with no traffic at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -186,6 +186,7 @@ struct Inner {
|
||||
routes: RwLock<HashMap<Ipv6Addr, WgPublicKey>>,
|
||||
next_index: AtomicU32,
|
||||
unroutable: AtomicU64,
|
||||
multicast: AtomicU64,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Inner {
|
||||
@@ -215,6 +216,7 @@ impl WireguardDevice {
|
||||
routes: RwLock::new(HashMap::new()),
|
||||
next_index: AtomicU32::new(1),
|
||||
unroutable: AtomicU64::new(0),
|
||||
multicast: AtomicU64::new(0),
|
||||
});
|
||||
|
||||
let reader = tokio::spawn(read_from_os(Arc::clone(&inner)));
|
||||
@@ -327,10 +329,22 @@ impl WireguardDevice {
|
||||
peers
|
||||
}
|
||||
|
||||
/// Packets the operating system sent that no peer owns the address for.
|
||||
/// Unicast packets the operating system sent to an address no peer owns.
|
||||
///
|
||||
/// A non-zero value means something tried to reach a host that is not in
|
||||
/// the overlay.
|
||||
pub fn unroutable_packets(&self) -> u64 {
|
||||
self.inner.unroutable.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Multicast packets dropped.
|
||||
///
|
||||
/// Expected and harmless: Linux emits multicast listener and router
|
||||
/// solicitation traffic on any IPv6 interface, and this overlay is
|
||||
/// unicast only. Counted separately so it does not look like a fault.
|
||||
pub fn multicast_packets(&self) -> u64 {
|
||||
self.inner.multicast.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WireguardDevice {
|
||||
@@ -407,6 +421,12 @@ async fn read_from_os(inner: Arc<Inner>) {
|
||||
inner.unroutable.fetch_add(1, Ordering::Relaxed);
|
||||
continue;
|
||||
};
|
||||
// The kernel emits multicast on every IPv6 interface. The overlay is
|
||||
// unicast only, so this is dropped, but it is not a fault.
|
||||
if destination.is_multicast() {
|
||||
inner.multicast.fetch_add(1, Ordering::Relaxed);
|
||||
continue;
|
||||
}
|
||||
let target = read_lock(&inner.routes).get(&destination).copied();
|
||||
let Some(target) = target else {
|
||||
inner.unroutable.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
@@ -152,8 +152,10 @@ pub struct NetworkOverview {
|
||||
pub overlay_prefix_len: u8,
|
||||
/// Peers this agent knows about.
|
||||
pub peers: Vec<PeerOverview>,
|
||||
/// Packets the operating system sent to an address no peer owns.
|
||||
/// Unicast packets the operating system sent to an address no peer owns.
|
||||
pub unroutable_packets: u64,
|
||||
/// Multicast packets dropped. Expected, not a fault.
|
||||
pub multicast_packets: u64,
|
||||
}
|
||||
|
||||
impl NetworkOverview {
|
||||
@@ -327,6 +329,11 @@ impl WireguardPlugin {
|
||||
.as_ref()
|
||||
.map(|device| device.unroutable_packets())
|
||||
.unwrap_or(0),
|
||||
multicast_packets: state
|
||||
.device
|
||||
.as_ref()
|
||||
.map(|device| device.multicast_packets())
|
||||
.unwrap_or(0),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user