networking

This commit is contained in:
Daman Mulye committed 2026-10-06 13:31:31 -07:00
1 parent a3a3249ccf
commit 2f9ebca6bb
6 files changed
+136 -8

No files matched your search

@@ -63,7 +63,7 @@ By default, the WSL2 virtual machine is created via the [Host Compute System (HC
gpuSupport=false
guiApplications=false
hostFileSystemAccess=false
networkingMode=none
networkingMode=nat
[experimental]
openVmm=true
@@ -74,7 +74,7 @@ OpenVMM currently does not support:
- ARM64 or UEFI boot
- GPU assignment or WSLg shared memory
- Persistent-memory or physical-disk devices
- Mirrored or bridged networking
- Mirrored or bridged networking, custom NAT addressing, Hyper-V firewall, DNS tunneling, or IPv6
- Nested virtualization, performance counters, or advanced memory controls
- Plan 9 file sharing or per-user virtio-fs options
+2
View File
@@ -28,6 +28,7 @@ set(SOURCES
LxssServerPort.cpp
MountSpecParsing.cpp
NatNetworking.cpp
OpenVmmNatNetworking.cpp
notifications.cpp
Redirector.cpp
registry.cpp
@@ -118,6 +119,7 @@ set(HEADERS
LxssServerPort.h
MountSpecParsing.h
NatNetworking.h
OpenVmmNatNetworking.h
notifications.h
precomp.h
Redirector.h
@@ -0,0 +1,50 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
#include "precomp.h"
#include "OpenVmmNatNetworking.h"
using wsl::core::OpenVmmNatNetworking;
VmNetworkAdapterRequest wsl::core::CreateOpenVmmNatNetworkAdapterRequest()
{
VmUserModeNatNetwork network;
constexpr std::array<BYTE, 6> clientMac{0x00, 0x00, 0x00, 0x00, 0x01, 0x00};
std::copy(clientMac.begin(), clientMac.end(), std::begin(network.Configuration.clientMac.bytes));
return {L"eth0", std::move(network)};
}
OpenVmmNatNetworking::OpenVmmNatNetworking(GnsChannel&& GnsChannel, bool EnableLocalhostRelay, int DhcpTimeout) :
m_gnsChannel(std::move(GnsChannel)), m_enableLocalhostRelay(EnableLocalhostRelay), m_dhcpTimeout(DhcpTimeout)
{
}
OpenVmmNatNetworking::~OpenVmmNatNetworking()
{
m_gnsChannel.Stop();
}
void OpenVmmNatNetworking::Initialize()
{
}
void OpenVmmNatNetworking::TraceLoggingRundown() noexcept
{
WSL_LOG(
"OpenVmmNatNetworking::TraceLoggingRundown",
TraceLoggingValue(m_enableLocalhostRelay, "localhostRelay"),
TraceLoggingValue(m_dhcpTimeout, "dhcpTimeout"));
}
void OpenVmmNatNetworking::FillInitialConfiguration(LX_MINI_INIT_NETWORKING_CONFIGURATION& Message)
{
Message.NetworkingMode = LxMiniInitNetworkingModeNat;
Message.DisableIpv6 = true;
Message.EnableDhcpClient = true;
Message.DhcpTimeout = static_cast<int>(std::round(m_dhcpTimeout / 1000.0));
Message.PortTrackerType = m_enableLocalhostRelay ? LxMiniInitPortTrackerTypeRelay : LxMiniInitPortTrackerTypeNone;
}
void OpenVmmNatNetworking::StartPortTracker(wil::unique_socket&&)
{
THROW_HR(E_NOTIMPL);
}
+30
View File
@@ -0,0 +1,30 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
#pragma once
#include "GnsChannel.h"
#include "INetworkingEngine.h"
#include "IVirtualMachineBackend.h"
namespace wsl::core {
VmNetworkAdapterRequest CreateOpenVmmNatNetworkAdapterRequest();
class OpenVmmNatNetworking : public INetworkingEngine
{
public:
OpenVmmNatNetworking(GnsChannel&& GnsChannel, bool EnableLocalhostRelay, int DhcpTimeout);
~OpenVmmNatNetworking() override;
void Initialize() override;
void TraceLoggingRundown() noexcept override;
void FillInitialConfiguration(LX_MINI_INIT_NETWORKING_CONFIGURATION& Message) override;
void StartPortTracker(wil::unique_socket&& Socket) override;
private:
GnsChannel m_gnsChannel;
bool m_enableLocalhostRelay;
int m_dhcpTimeout;
};
} // namespace wsl::core
+28 -4
View File
@@ -21,6 +21,7 @@ Abstract:
#include "disk.hpp"
#include "WslCoreInstance.h"
#include "NatNetworking.h"
#include "OpenVmmNatNetworking.h"
#include "BridgedNetworking.h"
#include "MirroredNetworking.h"
#include "WslCoreFirewallSupport.h"
@@ -569,8 +570,9 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
message->MemoryReclaimMode = static_cast<LX_MINI_INIT_MEMORY_RECLAIM_MODE>(m_vmConfig.MemoryReclaim);
message->EnableDebugShell = m_vmConfig.EnableDebugShell;
message->EnableSafeMode = m_vmConfig.EnableSafeMode;
// Consomme forwards DNS via the host proxy, so the dedicated DNS hvsocket is only used by NAT and Mirrored modes.
message->EnableDnsTunneling = m_vmConfig.EnableDnsTunneling && m_vmConfig.NetworkingMode != NetworkingMode::Consomme;
// User-mode NAT forwards DNS via the host proxy, so the dedicated DNS hvsocket is only used by HCS NAT and Mirrored modes.
message->EnableDnsTunneling = m_vmConfig.EnableDnsTunneling && m_vmConfig.NetworkingMode != NetworkingMode::Consomme &&
backendKind != BackendKind::OpenVmm;
message->DefaultKernel = m_defaultKernel;
message->IsolateDistroCgroup = m_vmConfig.IsolateDistroCgroup;
message->KernelModulesDeviceId = m_kernelModulesDeviceId;
@@ -600,7 +602,7 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
// For NAT networking, ensure the network can be created. If creating the network fails, fall back to
// Consomme networking mode.
wsl::windows::common::hcs::unique_hcn_network natNetwork;
if (m_vmConfig.NetworkingMode == NetworkingMode::Nat)
if (backendKind == BackendKind::Hcs && m_vmConfig.NetworkingMode == NetworkingMode::Nat)
{
{
SlowOperationWatcher slowOperation{"CreateNatNetwork"};
@@ -617,6 +619,22 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
// Create and initialize the networking engine.
const auto result = wil::ResultFromException(WI_DIAGNOSTICS_INFO, [&] {
if (backendKind == BackendKind::OpenVmm)
{
if (m_vmConfig.NetworkingMode == NetworkingMode::Nat)
{
m_networkingEngine = std::make_unique<wsl::core::OpenVmmNatNetworking>(
std::move(gnsChannel), m_vmConfig.EnableLocalhostRelay, m_vmConfig.DhcpTimeout);
m_networkingEngine->Initialize();
}
else
{
WI_ASSERT(m_vmConfig.NetworkingMode == NetworkingMode::None);
}
return;
}
// N.B. The existing networking engines still manage HCS resources directly. Keep this
// concrete escape hatch localized here until they are moved onto IVirtualMachineBackend.
auto& hcsBackend = static_cast<HcsVirtualMachineBackend&>(*m_backend);
@@ -1363,7 +1381,9 @@ void WslCoreVm::ValidateBackendConfiguration(BackendKind Backend) const
THROW_HR_IF_MSG(
notSupported, m_vmConfig.EnableHostFileSystemAccess, "OpenVMM host filesystem access is not integrated with WslCoreVm");
THROW_HR_IF_MSG(
notSupported, m_vmConfig.NetworkingMode != NetworkingMode::None, "OpenVMM networking is not integrated with WslCoreVm");
notSupported,
m_vmConfig.NetworkingMode != NetworkingMode::None && m_vmConfig.NetworkingMode != NetworkingMode::Nat,
"OpenVMM only supports NAT or disabled networking");
}
VmCreateRequest WslCoreVm::GenerateBackendRequest(const GUID& VmId, BackendKind Backend)
@@ -1550,6 +1570,10 @@ VmCreateRequest WslCoreVm::GenerateBackendRequest(const GUID& VmId, BackendKind
{
addBootDisk(L"kernel-modules", m_vmConfig.KernelModulesPath, m_privateKernelModules);
}
if (Backend == BackendKind::OpenVmm && m_vmConfig.NetworkingMode == NetworkingMode::Nat)
{
request.NetworkAdapters.emplace_back(wsl::core::CreateOpenVmmNatNetworkAdapterRequest());
}
return request;
}
@@ -2,6 +2,7 @@
#include "precomp.h"
#include "Common.h"
#include "OpenVmmNatNetworking.h"
#include "OpenVmmVirtualMachineBackend.h"
#include "VirtualMachineBackendTestHelpers.h"
@@ -110,10 +111,31 @@ class OpenVmmVirtualMachineBackendTests
VERIFY_ARE_EQUAL(c_notSupported, DescribeResult(request));
*feature = VmFeatureRequest::Disabled;
}
request.Memory.HostingProcessNameSuffix = L"WSL";
VERIFY_ARE_EQUAL(c_notSupported, DescribeResult(request));
}
TEST_METHOD(OpenVmmNatUsesCreationTimeAdapterAndGuestDhcp)
{
const auto request = wsl::core::CreateOpenVmmNatNetworkAdapterRequest();
VERIFY_ARE_EQUAL(L"eth0", request.Tag);
const auto& network = std::get<VmUserModeNatNetwork>(request.Configuration);
constexpr wsl::shared::string::MacAddress expectedMac{0x00, 0x00, 0x00, 0x00, 0x01, 0x00};
VERIFY_IS_TRUE(network.ClientMacAddress() == expectedMac);
auto [client, server] = MakeSocketPair();
wsl::core::OpenVmmNatNetworking networking(wsl::core::GnsChannel(std::move(server)), true, 5000);
LX_MINI_INIT_NETWORKING_CONFIGURATION configuration{};
networking.FillInitialConfiguration(configuration);
VERIFY_ARE_EQUAL(LxMiniInitNetworkingModeNat, configuration.NetworkingMode);
VERIFY_IS_TRUE(configuration.DisableIpv6);
VERIFY_IS_TRUE(configuration.EnableDhcpClient);
VERIFY_ARE_EQUAL(5, configuration.DhcpTimeout);
VERIFY_ARE_EQUAL(LxMiniInitPortTrackerTypeRelay, configuration.PortTrackerType);
}
TEST_METHOD(AllowsGuestAndSavedStateCrashCapture)
{
SKIP_TEST_ARM64();
@@ -243,10 +265,10 @@ class OpenVmmVirtualMachineBackendTests
TEST_METHOD(GuestShutdownTerminatesProcess)
{
SKIP_TEST_ARM64();
auto backend = OpenVmmVirtualMachineBackend::Create(CreateRunnableRequest());
auto terminationEvent = backend->GetTerminationEvent();
wil::unique_event callbackEvent{wil::EventOptions::ManualReset};
GUID callbackVmId{};
auto backend = OpenVmmVirtualMachineBackend::Create(CreateRunnableRequest());
auto terminationEvent = backend->GetTerminationEvent();
backend->RegisterTerminationCallback([&](GUID VmId) {
callbackVmId = VmId;
callbackEvent.SetEvent();