mirror of
https://github.com/aphrody-labs/WSL.git
synced 2026-10-17 12:45:55 +00:00
networking
This commit is contained in:
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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user