feat(client): refresh TAP IP diagnostics
The Windows client sampled TAP diagnostics once when opening the adapter. That can miss the useful DHCP result because the TAP interface may not receive a LAN address until after frame bridging starts. Keep the stable TAP diagnostics fields from startup, but retain the interface identity and re-read the TAP unicast IP whenever the periodic diagnostics tick prints and reports a snapshot. Later status lines can now show the DHCP address that arrives after the tunnel is already moving traffic. Test Plan: - cargo fmt --check - cargo test -p lanparty-client-win - cargo test --workspace - cargo clippy --workspace --all-targets -- -D warnings - git diff --check Refs: PLAN.md
This commit is contained in:
@@ -191,7 +191,8 @@ adapter may need to be disabled/enabled or reinstalled before it reloads the
|
|||||||
configured `NetworkAddress`.
|
configured `NetworkAddress`.
|
||||||
It prints and reports client diagnostics snapshots with relay reachability,
|
It prints and reports client diagnostics snapshots with relay reachability,
|
||||||
route-pinning, QUIC datagram budget, TAP status/IP, frame/datagram counters,
|
route-pinning, QUIC datagram budget, TAP status/IP, frame/datagram counters,
|
||||||
and drops.
|
and drops. The periodic diagnostics refresh the TAP unicast IP so DHCP results
|
||||||
|
that arrive after bridging starts become visible in later status lines.
|
||||||
Relay lifecycle events are logged as they arrive, including gateway joins and
|
Relay lifecycle events are logged as they arrive, including gateway joins and
|
||||||
peer leaves. The client remembers peer identities from join and catch-up events
|
peer leaves. The client remembers peer identities from join and catch-up events
|
||||||
so later leave logs can identify a disconnected LAN gateway or client MAC when
|
so later leave logs can identify a disconnected LAN gateway or client MAC when
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#[cfg(windows)]
|
use std::{
|
||||||
use std::net::IpAddr;
|
collections::BTreeMap,
|
||||||
use std::{collections::BTreeMap, fs, net::SocketAddr, path::PathBuf};
|
fs,
|
||||||
|
net::{IpAddr, SocketAddr},
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use std::{
|
use std::{
|
||||||
sync::{Arc, mpsc},
|
sync::{Arc, mpsc},
|
||||||
@@ -139,6 +142,7 @@ async fn run_client(session: &ClientSession, relay_route_pin: &PinnedRelayRoute)
|
|||||||
let OpenedTapAdapter {
|
let OpenedTapAdapter {
|
||||||
tap,
|
tap,
|
||||||
tap_diagnostics,
|
tap_diagnostics,
|
||||||
|
tap_interface,
|
||||||
_route_guard,
|
_route_guard,
|
||||||
} = open_tap_adapter(session)?;
|
} = open_tap_adapter(session)?;
|
||||||
let relay_route =
|
let relay_route =
|
||||||
@@ -147,7 +151,11 @@ async fn run_client(session: &ClientSession, relay_route_pin: &PinnedRelayRoute)
|
|||||||
print_verified_relay_route(&relay_route);
|
print_verified_relay_route(&relay_route);
|
||||||
print_and_report_client_diagnostics(
|
print_and_report_client_diagnostics(
|
||||||
session,
|
session,
|
||||||
&client_diagnostics_snapshot(session, true, tap_diagnostics.clone()),
|
&client_diagnostics_snapshot(
|
||||||
|
session,
|
||||||
|
true,
|
||||||
|
current_tap_diagnostics(&tap_diagnostics, tap_interface),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
println!(
|
println!(
|
||||||
@@ -186,7 +194,11 @@ async fn run_client(session: &ClientSession, relay_route_pin: &PinnedRelayRoute)
|
|||||||
_ = diagnostics_check.tick() => {
|
_ = diagnostics_check.tick() => {
|
||||||
print_and_report_client_diagnostics(
|
print_and_report_client_diagnostics(
|
||||||
session,
|
session,
|
||||||
&client_diagnostics_snapshot(session, true, tap_diagnostics.clone()),
|
&client_diagnostics_snapshot(
|
||||||
|
session,
|
||||||
|
true,
|
||||||
|
current_tap_diagnostics(&tap_diagnostics, tap_interface),
|
||||||
|
),
|
||||||
).await;
|
).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,6 +325,7 @@ fn route_next_hop_label(next_hop: Option<std::net::IpAddr>) -> String {
|
|||||||
struct OpenedTapAdapter {
|
struct OpenedTapAdapter {
|
||||||
tap: TapAdapter,
|
tap: TapAdapter,
|
||||||
tap_diagnostics: TapDiagnostics,
|
tap_diagnostics: TapDiagnostics,
|
||||||
|
tap_interface: NetworkInterfaceIdentity,
|
||||||
_route_guard: TapRouteProtectionGuard,
|
_route_guard: TapRouteProtectionGuard,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,17 +366,17 @@ fn open_tap_adapter(session: &ClientSession) -> Result<OpenedTapAdapter> {
|
|||||||
tap_interface.index(),
|
tap_interface.index(),
|
||||||
tap_interface.luid()
|
tap_interface.luid()
|
||||||
);
|
);
|
||||||
let tap_ip = tap_unicast_ip(tap_interface);
|
|
||||||
let tap_diagnostics = TapDiagnostics::new(
|
let tap_diagnostics = TapDiagnostics::new(
|
||||||
true,
|
true,
|
||||||
Some(driver_mac),
|
Some(driver_mac),
|
||||||
Some(session.welcome().effective_tap_mtu()),
|
Some(session.welcome().effective_tap_mtu()),
|
||||||
tap_ip,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(OpenedTapAdapter {
|
Ok(OpenedTapAdapter {
|
||||||
tap,
|
tap,
|
||||||
tap_diagnostics,
|
tap_diagnostics,
|
||||||
|
tap_interface,
|
||||||
_route_guard: route_guard,
|
_route_guard: route_guard,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -398,6 +411,19 @@ fn client_diagnostics_snapshot(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn current_tap_diagnostics(
|
||||||
|
base: &TapDiagnostics,
|
||||||
|
identity: NetworkInterfaceIdentity,
|
||||||
|
) -> TapDiagnostics {
|
||||||
|
tap_diagnostics_with_ip(base, tap_unicast_ip(identity))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(windows), allow(dead_code))]
|
||||||
|
fn tap_diagnostics_with_ip(base: &TapDiagnostics, ip: Option<IpAddr>) -> TapDiagnostics {
|
||||||
|
TapDiagnostics::new(base.adapter_found(), base.mac(), base.mtu(), ip)
|
||||||
|
}
|
||||||
|
|
||||||
fn print_client_diagnostics(diagnostics: &ClientDiagnostics) {
|
fn print_client_diagnostics(diagnostics: &ClientDiagnostics) {
|
||||||
println!("{}", format_client_diagnostics(diagnostics));
|
println!("{}", format_client_diagnostics(diagnostics));
|
||||||
}
|
}
|
||||||
@@ -801,6 +827,24 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn refreshes_tap_diagnostics_ip_without_losing_static_fields() {
|
||||||
|
let base = TapDiagnostics::new(
|
||||||
|
true,
|
||||||
|
Some(mac(1)),
|
||||||
|
Some(1200),
|
||||||
|
Some("169.254.10.20".parse().unwrap()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let refreshed =
|
||||||
|
tap_diagnostics_with_ip(&base, Some("10.73.42.51".parse::<IpAddr>().unwrap()));
|
||||||
|
|
||||||
|
assert!(refreshed.adapter_found());
|
||||||
|
assert_eq!(refreshed.mac(), Some(mac(1)));
|
||||||
|
assert_eq!(refreshed.mtu(), Some(1200));
|
||||||
|
assert_eq!(refreshed.ip().unwrap().to_string(), "10.73.42.51");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn formats_relay_lifecycle_events() {
|
fn formats_relay_lifecycle_events() {
|
||||||
let gateway = ControlMessage::PeerJoined(PeerInfo::new(1, Role::Gateway, None).unwrap());
|
let gateway = ControlMessage::PeerJoined(PeerInfo::new(1, Role::Gateway, None).unwrap());
|
||||||
|
|||||||
Reference in New Issue
Block a user