fix(obs): warn on TAP link-local IPv4
IPv4 link-local on the TAP adapter means Windows self-assigned APIPA because LAN DHCP did not complete through the tunnel. The previous user diagnostic only said "TAP IP detected", which made a failed DHCP path look neutral during MVP testing. Return a full UserDiagnostic from TAP IP classification so IPv4 link-local can be a warning while normal IPv4 still reports the received DHCP address. Keep IPv6 link-local neutral because it is expected on many Windows interfaces and is not evidence of LAN DHCP success or failure. TESTING.md now tells the operator to troubleshoot 169.254.x.x like `Waiting for TAP IP`. Test Plan: - cargo test -p lanparty-obs - cargo test -p lanparty-client-win - cargo test --workspace - cargo clippy --workspace --all-targets -- -D warnings - cargo fmt --check - git diff --check Refs: PLAN.md diagnostics; TESTING.md MVP guide
This commit is contained in:
@@ -242,6 +242,10 @@ If the client says `Waiting for TAP IP`, DHCP is not making the full round trip.
|
|||||||
Check relay/gateway frame logs for broadcast traffic and check that the gateway
|
Check relay/gateway frame logs for broadcast traffic and check that the gateway
|
||||||
is on wired Ethernet.
|
is on wired Ethernet.
|
||||||
|
|
||||||
|
If the client reports a TAP link-local address such as `169.254.x.x`, treat it
|
||||||
|
the same way: Windows has self-assigned an address, but LAN DHCP did not
|
||||||
|
complete through the tunnel.
|
||||||
|
|
||||||
If startup fails with a TAP MAC mismatch, disable/enable the TAP adapter or
|
If startup fails with a TAP MAC mismatch, disable/enable the TAP adapter or
|
||||||
reinstall TAP-Windows6 so Windows reloads the `NetworkAddress` value. Do not
|
reinstall TAP-Windows6 so Windows reloads the `NetworkAddress` value. Do not
|
||||||
continue with a mismatched MAC.
|
continue with a mismatched MAC.
|
||||||
|
|||||||
@@ -434,8 +434,8 @@ impl ClientDiagnostics {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(message) = tap_ip_user_message(self.tap.ip()) {
|
if let Some(diagnostic) = tap_ip_user_diagnostic(self.tap.ip()) {
|
||||||
diagnostics.push(UserDiagnostic::new(UserDiagnosticLevel::Info, message));
|
diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(rtt_ms) = self.quic.relay_rtt_ms() {
|
if let Some(rtt_ms) = self.quic.relay_rtt_ms() {
|
||||||
@@ -456,10 +456,20 @@ impl ClientDiagnostics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tap_ip_user_message(ip: Option<IpAddr>) -> Option<String> {
|
fn tap_ip_user_diagnostic(ip: Option<IpAddr>) -> Option<UserDiagnostic> {
|
||||||
match ip {
|
match ip {
|
||||||
Some(IpAddr::V4(ip)) if !ip.is_link_local() => Some(format!("DHCP received: {ip}")),
|
Some(IpAddr::V4(ip)) if ip.is_link_local() => Some(UserDiagnostic::new(
|
||||||
Some(ip) => Some(format!("TAP IP detected: {ip}")),
|
UserDiagnosticLevel::Warning,
|
||||||
|
format!("TAP has link-local IP {ip}; waiting for LAN DHCP"),
|
||||||
|
)),
|
||||||
|
Some(IpAddr::V4(ip)) => Some(UserDiagnostic::new(
|
||||||
|
UserDiagnosticLevel::Info,
|
||||||
|
format!("DHCP received: {ip}"),
|
||||||
|
)),
|
||||||
|
Some(ip) => Some(UserDiagnostic::new(
|
||||||
|
UserDiagnosticLevel::Info,
|
||||||
|
format!("TAP IP detected: {ip}"),
|
||||||
|
)),
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -712,14 +722,21 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn avoids_calling_link_local_tap_ip_dhcp() {
|
fn reports_link_local_tap_ipv4_as_waiting_for_lan_dhcp() {
|
||||||
|
let diagnostic = tap_ip_user_diagnostic(Some("169.254.10.20".parse().unwrap())).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(diagnostic.level(), UserDiagnosticLevel::Warning);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tap_ip_user_message(Some("169.254.10.20".parse().unwrap())),
|
diagnostic.message(),
|
||||||
Some("TAP IP detected: 169.254.10.20".to_string())
|
"TAP has link-local IP 169.254.10.20; waiting for LAN DHCP"
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
tap_ip_user_message(Some("fe80::1".parse().unwrap())),
|
|
||||||
Some("TAP IP detected: fe80::1".to_string())
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reports_ipv6_link_local_tap_ip_without_calling_it_dhcp() {
|
||||||
|
let diagnostic = tap_ip_user_diagnostic(Some("fe80::1".parse().unwrap())).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(diagnostic.level(), UserDiagnosticLevel::Info);
|
||||||
|
assert_eq!(diagnostic.message(), "TAP IP detected: fe80::1");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user