Mark routes via a link-local gateway as onlink in the guest#41003
Draft
benhillis wants to merge 1 commit into
Draft
Mark routes via a link-local gateway as onlink in the guest#41003benhillis wants to merge 1 commit into
benhillis wants to merge 1 commit into
Conversation
GnsEngine adds a default route via the link-local NAT gateway (169.254.254.1). When the guest interface has no on-link prefix covering that gateway (e.g. a mirrored host address plumbed as a /32), the kernel rejects the route add with ENETUNREACH. In wslc this aborts ConfigureNetworking, kills /gns, and fails session creation, surfacing to the user as "Catastrophic failure / E_UNEXPECTED". A link-local next hop is only ever reachable on-link, so set RTNH_F_ONLINK for any route whose gateway is link-local (169.254.0.0/16 or fe80::/10). This bypasses the kernel reachability check and has no effect on NAT gateways, which are not link-local. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a guest-side networking failure that causes wslc run <image> to fail with E_UNEXPECTED on some hosts by ensuring routes that use a link-local gateway are treated as on-link by the Linux kernel during netlink route programming.
Changes:
- Add link-local detection for IPv4 (
169.254.0.0/16) and IPv6 (fe80::/10) addresses. - Mark routes that use a link-local gateway with an “onlink” flag during netlink message construction.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/linux/netlinkutil/RoutingTable.cpp | Sets an onlink-related flag when a route’s gateway is link-local during netlink route message creation. |
| src/linux/netlinkutil/address.h | Adds Address::IsLinkLocal() API to classify link-local addresses. |
| src/linux/netlinkutil/Address.cpp | Implements IsLinkLocal() for IPv4 and IPv6 address families. |
Comment on lines
139
to
+145
| message.route.rtm_type = route.IsMulticast() ? RTN_MULTICAST : RTN_UNICAST; | ||
| message.route.rtm_scope = route.IsOnlink() ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE; | ||
| message.route.rtm_flags = RTM_F_NOTIFY; | ||
| if (route.via.has_value() && route.via.value().IsLinkLocal()) | ||
| { | ||
| message.route.rtm_flags |= RTNH_F_ONLINK; | ||
| } |
Comment on lines
+144
to
+153
| bool Address::IsLinkLocal() const | ||
| { | ||
| if (m_family == AF_INET) | ||
| { | ||
| return (ntohl(AsBytes<in_addr>().s_addr) & 0xFFFF0000) == 0xA9FE0000; | ||
| } | ||
|
|
||
| const auto bytes = AsBytes<in6_addr>(); | ||
| return bytes.s6_addr[0] == 0xFE && (bytes.s6_addr[1] & 0xC0) == 0x80; | ||
| } |
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
wslc run <image>fails immediately withCatastrophic failure / Error code: E_UNEXPECTEDon some hosts (reported in #41002). The generic error hides a guest-side networking failure: the default route add is rejected by the kernel, which aborts VM networking setup and session creation.Root cause
Trace (
logs.etl) from #41002 shows the failure chain:10.251.12.145/32, empty gateway).0.0.0.0/0 via 169.254.254.1(the link-local NAT gateway).GnsChannel.cpp:68->HcsVirtualMachine.cpp:518(ConfigureNetworking) ->WSLCVirtualMachine.cpp:417THROW_IF_FAILED->/gnsexits ->WSLCInit.cpp:1244 "No child process"->WSLCSessionManager.cpp:358 "Failed to create session"->wslcprintsE_UNEXPECTED.With a
/32interface there is no on-link prefix covering169.254.254.1, so the kernel refuses to add a default route through a gateway it considers unreachable.Fix
A link-local next hop (IPv4
169.254.0.0/16, IPv6fe80::/10) is non-routable and only ever reachable on-link, so a route through it must be markedRTNH_F_ONLINK. This is set in the sharedRoutingTable::SendMessage, so it applies to the default route (and any offlink route) whenever the gateway is link-local. NAT gateways are ordinary private IPs (not link-local), so this path is a no-op for them and there is no change to existing NAT/mirrored behavior.Verification
ip ... onlinksets exactly theRTNH_F_ONLINKflag this change sets.libnetlinkutilviacmake --build . --target libnetlinkutil(cross toolchain) - compiles clean.Notes
This resolves the reported crash. End-to-end connectivity on the reporter's corporate/VPN host has not been validated live; there is no evidence of a second fault in the logs (everything up to the route add succeeded).
Fixes #41002