Fix mirrored networking loopback endpoint creation failure#14081
Fix mirrored networking loopback endpoint creation failure#14081benm-dev wants to merge 6 commits intomicrosoft:masterfrom
Conversation
|
@microsoft-github-policy-service agree |
There was a problem hiding this comment.
Pull request overview
This PR fixes a critical bug in mirrored networking mode where loopback endpoint creation fails after Windows update KB5074109. The fix detects loopback networks and uses simplified endpoint settings without firewall policies to avoid HCN error 0x803B001B.
Changes:
- Added loopback network detection logic to skip firewall policy application
- Created separate endpoint configuration path for loopback networks using HostComputeNetwork
- Extended HNSNetwork schema to include IsLoopback property for network type detection
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/windows/service/exe/MirroredNetworking.cpp | Added conditional logic to detect loopback networks and configure endpoints without firewall policies, using HostComputeNetwork instead of VirtualNetwork |
| src/shared/inc/hns_schema.h | Added IsLoopback boolean field to HNSNetwork struct with JSON serialization support |
|
lgtm |
|
Is this the same as issue #13454 |
|
Doesn't look like it, that is more generic and solvable by resetting the adapter as the reply here |
|
@keith-horton - does this look reasonable to you? Do you have any context on the Windows change that recently broke this? |
The fix referred to in that KB article was not in WSL - it was in other parts of the TCPIP / vswitch stack - where we addressed a perf issue, but the NBL (kernel structure representing one or more packets) could have fields that some VPN vendors did not expect (though was perfectly legal) -- which was exercised in the WSL path. So we had to revert that and fix it in a way that did not break some VPNs. So I don't know what would have changed that would have affected the above. The author of this PR is correct: Hyper-V Firewall rules do not affect the loopback path. |
keith-horton
left a comment
There was a problem hiding this comment.
Thank you for doing this investigation and testing.
WSL supports older versions of Windows that does not support Hyper-V Firewall. This looks correct to me - minus the change I noted below.
| // Loopback networks require HostComputeNetwork (not VirtualNetwork) and don't support policies | ||
| hns::HostComputeEndpoint hnsEndpoint{}; | ||
| hnsEndpoint.HostComputeNetwork = NetworkId; | ||
| hnsEndpoint.SchemaVersion.Major = 2; |
There was a problem hiding this comment.
nit: assuming these version numbers are hardcoded elsewhere too. Would be good to declare named constant that can be repeatedly used
There was a problem hiding this comment.
yeah I worry a little bit about this schema version, do we know everywhere that supports mirrored networking supports 2.16?
|
Hi @keith-horton , I updated this in commit c61ba69 - the condition now reads: else if (m_config.FirewallConfig.Enabled() && isLoopbackNetwork)The diff you're viewing is marked "Outdated" which shows the old code. Let me know if there's anything else needed! |
keith-horton
left a comment
There was a problem hiding this comment.
Great. Thanks for doing this!
65c96d9 to
94ac6f9
Compare
|
Can't wait till it find the way to production soon! thanks a lot |
|
Is there an update on when this PR will be merged and a new release created? |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/windows/service/exe/MirroredNetworking.cpp:501
- Loopback networks are only handled specially when Hyper-V Firewall is enabled. If
properties.IsLoopbackis true andm_config.FirewallConfig.Enabled()is false, the code still builds endpoint settings withHNSEndpoint::VirtualNetwork = NetworkId, but the comment/PR description states loopback endpoints requireHostComputeNetworkand fail when created with the other schema. Consider moving the loopback handling outside the firewall-enabled branch so loopback endpoints always useHostComputeEndpoint(without policies) regardless of firewall configuration.
else if (m_config.FirewallConfig.Enabled() && isLoopbackNetwork)
{
// Loopback networks require HostComputeNetwork (not VirtualNetwork) and don't support policies
hns::HostComputeEndpoint hnsEndpoint{};
hnsEndpoint.HostComputeNetwork = NetworkId;
hnsEndpoint.SchemaVersion.Major = 2;
hnsEndpoint.SchemaVersion.Minor = 16;
endpointSettings = ToJsonW(hnsEndpoint);
}
else
{
// If Hyper-V Firewall is not supported for this scenario, only configure the basic HNS endpoint object
wsl::shared::hns::HNSEndpoint settings{};
settings.VirtualNetwork = NetworkId;
endpointSettings = ToJsonW(settings);
}
| // Loopback networks don't support firewall policies - creating an endpoint with firewall | ||
| // policies on a loopback network will fail with HCN error 0x803B001B ("Invalid JSON document | ||
| // string"). This behavior changed in KB5074109. Additionally, loopback networks require | ||
| // HostComputeNetwork instead of VirtualNetwork in the endpoint settings. | ||
| // See: https://github.com/microsoft/WSL/issues/14080 | ||
| const bool isLoopbackNetwork = properties.IsLoopback; |
9d6818f to
e57f5cf
Compare
## Problem
After installing KB5074109 (January 2026), WSL mirrored networking fails to
create the loopback endpoint, causing localhost (127.0.0.1) TCP/UDP connections
to fail. Users see the loopback0 interface in state DOWN with NO-CARRIER.
## Root Cause Analysis
HNS loopback networks no longer accept firewall policies when creating
endpoints. Direct HCN API testing confirms:
- Test 1: Endpoint WITH firewall policy -> 0x803B001B (FAIL)
Error: 'Invalid JSON document string. {{Policies.VmCreatorId,UnknownField}}'
- Test 2: Endpoint with VirtualNetwork field -> 0x803B001B (FAIL)
Error: 'Invalid JSON document string. {{VirtualNetwork,UnknownField}}'
- Test 3: Endpoint with HostComputeNetwork only -> 0x00000000 (SUCCESS)
The current code in MirroredNetworking::AddNetworkEndpoint() creates all
endpoints with firewall policies when m_config.FirewallConfig.Enabled() is
true (the default), causing loopback endpoint creation to fail silently.
## Solution
- Add IsLoopback field to HNSNetwork struct to detect loopback networks
- Skip firewall policies when creating endpoints on loopback networks
- Use HostComputeNetwork instead of VirtualNetwork for loopback endpoints
## Testing
Verified on Windows Build 26220.7535:
1. HCN API tests confirm endpoint creation succeeds without firewall policies
2. WSL localhost TCP connectivity works when loopback0 is properly configured
Fixes microsoft#14080
Related: microsoft#14063
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
fa21b2b to
1004388
Compare
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
@benm-dev - sorry this one slipped through the cracks, taking a look now. |
|
Commenter does not have sufficient privileges for PR 14081 in repo microsoft/WSL |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| bool IsLoopback{}; | ||
|
|
||
| NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(HNSNetwork, ID, Name, SourceMac, DNSSuffix, DNSServerList, DNSDomain, Subnets, Flags, InterfaceConstraint); | ||
| NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(HNSNetwork, ID, Name, SourceMac, DNSSuffix, DNSServerList, DNSDomain, Subnets, Flags, InterfaceConstraint, IsLoopback); |
There was a problem hiding this comment.
Adding IsLoopback to NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT changes both deserialization and serialization for HNSNetwork. If HNSNetwork is ever serialized for outbound HNS/HCN requests, this will now emit an IsLoopback field (default false), which could be rejected as an unexpected property. Consider either (1) making IsLoopback response-only via a custom to_json/from_json that omits it on serialization, or (2) splitting request vs response DTOs so response-only properties don’t get sent back to the platform.
| NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(HNSNetwork, ID, Name, SourceMac, DNSSuffix, DNSServerList, DNSDomain, Subnets, Flags, InterfaceConstraint, IsLoopback); | |
| friend void to_json(nlohmann::json& Json, const HNSNetwork& Network) | |
| { | |
| Json = nlohmann::json{ | |
| {"ID", Network.ID}, | |
| {"Name", Network.Name}, | |
| {"SourceMac", Network.SourceMac}, | |
| {"DNSSuffix", Network.DNSSuffix}, | |
| {"DNSServerList", Network.DNSServerList}, | |
| {"DNSDomain", Network.DNSDomain}, | |
| {"Subnets", Network.Subnets}, | |
| {"Flags", Network.Flags}, | |
| {"InterfaceConstraint", Network.InterfaceConstraint}, | |
| }; | |
| } | |
| friend void from_json(const nlohmann::json& Json, HNSNetwork& Network) | |
| { | |
| Network = HNSNetwork{}; | |
| if (const auto Entry = Json.find("ID"); Entry != Json.end() && !Entry->is_null()) | |
| { | |
| Entry->get_to(Network.ID); | |
| } | |
| if (const auto Entry = Json.find("Name"); Entry != Json.end() && !Entry->is_null()) | |
| { | |
| Entry->get_to(Network.Name); | |
| } | |
| if (const auto Entry = Json.find("SourceMac"); Entry != Json.end() && !Entry->is_null()) | |
| { | |
| Entry->get_to(Network.SourceMac); | |
| } | |
| if (const auto Entry = Json.find("DNSSuffix"); Entry != Json.end() && !Entry->is_null()) | |
| { | |
| Entry->get_to(Network.DNSSuffix); | |
| } | |
| if (const auto Entry = Json.find("DNSServerList"); Entry != Json.end() && !Entry->is_null()) | |
| { | |
| Entry->get_to(Network.DNSServerList); | |
| } | |
| if (const auto Entry = Json.find("DNSDomain"); Entry != Json.end() && !Entry->is_null()) | |
| { | |
| Entry->get_to(Network.DNSDomain); | |
| } | |
| if (const auto Entry = Json.find("Subnets"); Entry != Json.end() && !Entry->is_null()) | |
| { | |
| Entry->get_to(Network.Subnets); | |
| } | |
| if (const auto Entry = Json.find("Flags"); Entry != Json.end() && !Entry->is_null()) | |
| { | |
| Entry->get_to(Network.Flags); | |
| } | |
| if (const auto Entry = Json.find("InterfaceConstraint"); Entry != Json.end() && !Entry->is_null()) | |
| { | |
| Entry->get_to(Network.InterfaceConstraint); | |
| } | |
| if (const auto Entry = Json.find("IsLoopback"); Entry != Json.end() && !Entry->is_null()) | |
| { | |
| Entry->get_to(Network.IsLoopback); | |
| } | |
| } |
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
@benm-dev — latest CI is failing on formatting checks. Please rebase on master and run |
Summary of the Pull Request
Fix loopback endpoint creation failure in mirrored networking mode after KB5074109.
PR Checklist
Detailed Description
After KB5074109, HNS loopback networks reject firewall policies when creating endpoints, returning error 0x803B001B. This fix detects loopback networks via
IsLoopbackproperty and uses simplified endpoint settings without policies.Validation Steps Performed