Update Microsoft.WSL.DeviceHost with virtiofs and virtio networking (#14198)
improvements. Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Ben Hillis committed
Feb 12, 2026 at 13:05 UTC
66822ce4cef4315af56e167a3beae19a9ebf26f0
7 files changed
+145
-291
packages.config
+1
-1
@@ -18,7 +18,7 @@
18
<package id="Microsoft.WSL.bsdtar" version="0.0.2-2" />
19
<package id="Microsoft.WSL.Dependencies.amd64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" />
20
<package id="Microsoft.WSL.Dependencies.arm64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" />
21
- <package id="Microsoft.WSL.DeviceHost" version="1.1.10-0" />
21
+ <package id="Microsoft.WSL.DeviceHost" version="1.1.14-0" />
22
<package id="Microsoft.WSL.Kernel" version="6.6.114.1-1" targetFramework="native" />
23
<package id="Microsoft.WSL.LinuxSdk" version="1.20.0" targetFramework="native" />
24
<package id="Microsoft.WSL.TestDistro" version="2.5.7-47" />
src/windows/common/VirtioNetworking.cpp
+119
-224
@@ -11,14 +11,15 @@ using namespace wsl::shared;
11
using namespace wsl::windows::common::stringify;
12
using wsl::core::VirtioNetworking;
13
14
+static constexpr auto c_eth0DeviceName = L"eth0";
15
static constexpr auto c_loopbackDeviceName = TEXT(LX_INIT_LOOPBACK_DEVICE_NAME);
16
17
VirtioNetworking::VirtioNetworking(
17
- GnsChannel&& gnsChannel, bool enableLocalhostRelay, LPCWSTR dnsOptions, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken) :
18
+ GnsChannel&& gnsChannel, VirtioNetworkingFlags flags, LPCWSTR dnsOptions, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken) :
19
m_guestDeviceManager(std::move(guestDeviceManager)),
20
m_userToken(std::move(userToken)),
21
m_gnsChannel(std::move(gnsChannel)),
21
- m_enableLocalhostRelay(enableLocalhostRelay),
22
+ m_flags(flags),
23
m_dnsOptions(dnsOptions)
24
{
25
}
@@ -27,95 +28,22 @@ VirtioNetworking::~VirtioNetworking()
28
{
29
// Unregister the network notification callback to prevent it from using the GNS channel.
30
m_networkNotifyHandle.reset();
31
+
32
// Stop the GNS channel to unblock any stuck communications with the guest.
33
m_gnsChannel.Stop();
34
}
35
36
void VirtioNetworking::Initialize()
37
{
36
- m_networkSettings = GetHostEndpointSettings();
37
-
38
- // TODO: Determine gateway MAC address
39
- std::wstringstream device_options;
40
- auto client_ip = m_networkSettings->PreferredIpAddress.AddressString;
41
- if (!client_ip.empty())
42
- {
43
- if (device_options.tellp() > 0)
44
- {
45
- device_options << L";";
46
- }
47
- device_options << L"client_ip=" << client_ip;
48
- }
49
-
50
- if (!m_networkSettings->MacAddress.empty())
51
- {
52
- if (device_options.tellp() > 0)
53
- {
54
- device_options << L";";
55
- }
56
- device_options << L"client_mac=" << m_networkSettings->MacAddress;
57
- }
58
-
59
- std::wstring default_route = m_networkSettings->GetBestGatewayAddressString();
60
- if (!default_route.empty())
61
- {
62
- if (device_options.tellp() > 0)
63
- {
64
- device_options << L";";
65
- }
66
- device_options << L"gateway_ip=" << default_route;
67
- }
68
-
69
- // Get initial DNS settings for device options.
70
- auto initialDns = networking::HostDnsInfo::GetDnsSettings(networking::DnsSettingsFlags::IncludeVpn);
71
- if (!initialDns.Servers.empty())
72
- {
73
- if (device_options.tellp() > 0)
74
- {
75
- device_options << L";";
76
- }
77
- device_options << L"nameservers=" << wsl::shared::string::MultiByteToWide(wsl::shared::string::Join(initialDns.Servers, ','));
78
- }
79
-
80
- auto lock = m_lock.lock_exclusive();
81
-
82
- // Add virtio net adapter to guest
83
- m_adapterId = m_guestDeviceManager->AddGuestDevice(
84
- VIRTIO_NET_DEVICE_ID, VIRTIO_NET_CLASS_ID, L"eth0", nullptr, device_options.str().c_str(), 0, m_userToken.get());
85
-
86
- hns::HNSEndpoint endpointProperties;
87
- endpointProperties.ID = m_adapterId;
88
- endpointProperties.IPAddress = m_networkSettings->PreferredIpAddress.AddressString;
89
- endpointProperties.PrefixLength = m_networkSettings->PreferredIpAddress.PrefixLength;
90
- m_gnsChannel.SendEndpointState(endpointProperties);
38
+ // Initialize adapter state.
39
+ RefreshGuestConnection();
40
92
- // N.B. The MAC address is advertised with the virtio device so doesn't need to be explicitly set.
93
-
94
- // Send the default route to gns
95
- if (!default_route.empty())
96
- {
97
- wsl::shared::hns::Route route;
98
- route.NextHop = default_route;
99
- route.DestinationPrefix = LX_INIT_DEFAULT_ROUTE_PREFIX;
100
- route.Family = AF_INET;
101
-
102
- hns::ModifyGuestEndpointSettingRequest<hns::Route> request;
103
- request.RequestType = hns::ModifyRequestType::Add;
104
- request.ResourceType = hns::GuestEndpointResourceType::Route;
105
- request.Settings = route;
106
- m_gnsChannel.SendHnsNotification(ToJsonW(request).c_str(), m_adapterId);
107
- }
108
-
109
- // Send the initial DNS configuration to GNS and track it.
110
- m_trackedDnsSettings = initialDns;
111
- SendDnsUpdate(initialDns);
112
-
113
- if (m_enableLocalhostRelay)
41
+ if (WI_IsFlagSet(m_flags, VirtioNetworkingFlags::LocalhostRelay))
42
{
43
SetupLoopbackDevice();
44
}
45
118
- THROW_IF_WIN32_ERROR(NotifyNetworkConnectivityHintChange(&VirtioNetworking::OnNetworkConnectivityChange, this, true, &m_networkNotifyHandle));
46
+ THROW_IF_WIN32_ERROR(NotifyNetworkConnectivityHintChange(&VirtioNetworking::OnNetworkConnectivityChange, this, TRUE, &m_networkNotifyHandle));
47
}
48
49
void VirtioNetworking::SetupLoopbackDevice()
@@ -129,22 +57,21 @@ void VirtioNetworking::SetupLoopbackDevice()
57
0,
58
m_userToken.get());
59
132
- hns::HNSEndpoint endpointProperties;
133
- endpointProperties.ID = m_localhostAdapterId;
60
// The loopback gateway (see LX_INIT_IPV4_LOOPBACK_GATEWAY_ADDRESS) is 169.254.73.152, so assign loopback0 an
61
// address of 169.254.73.153 with a netmask of 30 so that the only addresses associated with this adapter are
62
// itself and the gateway.
63
+ // N.B. The MAC address is advertised with the virtio device so doesn't need to be explicitly set.
64
+ hns::HNSEndpoint endpointProperties;
65
+ endpointProperties.ID = m_localhostAdapterId.value();
66
endpointProperties.IPAddress = L"169.254.73.153";
67
endpointProperties.PrefixLength = 30;
68
endpointProperties.PortFriendlyName = c_loopbackDeviceName;
69
m_gnsChannel.SendEndpointState(endpointProperties);
70
142
- // N.B. The MAC address is advertised with the virtio device so doesn't need to be explicitly set.
143
-
71
hns::CreateDeviceRequest createLoopbackDevice;
72
createLoopbackDevice.deviceName = c_loopbackDeviceName;
73
createLoopbackDevice.type = hns::DeviceType::Loopback;
147
- createLoopbackDevice.lowerEdgeAdapterId = m_localhostAdapterId;
74
+ createLoopbackDevice.lowerEdgeAdapterId = m_localhostAdapterId.value();
75
constexpr auto loopbackType = GnsMessageType(createLoopbackDevice);
76
m_gnsChannel.SendNetworkDeviceMessage(loopbackType, ToJsonW(createLoopbackDevice).c_str());
77
}
@@ -175,7 +102,7 @@ HRESULT VirtioNetworking::HandlePortNotification(const SOCKADDR_INET& addr, int
102
}
103
}
104
178
- if (m_enableLocalhostRelay && (unspecified || loopback))
105
+ if (WI_IsFlagSet(m_flags, VirtioNetworkingFlags::LocalhostRelay) && (unspecified || loopback))
106
{
107
SOCKADDR_INET localAddr = addr;
108
if (!loopback)
@@ -191,13 +118,14 @@ HRESULT VirtioNetworking::HandlePortNotification(const SOCKADDR_INET& addr, int
118
}
119
}
120
result = ModifyOpenPorts(c_loopbackDeviceName, localAddr, protocol, allocate);
194
- LOG_HR_IF_MSG(E_FAIL, result != S_OK, "Failure adding localhost relay port %d", localAddr.Ipv4.sin_port);
121
+ LOG_HR_IF_MSG(
122
+ E_FAIL, result != S_OK, "Failure adding localhost relay port %d", INETADDR_PORT(reinterpret_cast<const SOCKADDR*>(&localAddr)));
123
}
124
125
if (!loopback)
126
{
199
- const int localResult = ModifyOpenPorts(L"eth0", addr, protocol, allocate);
200
- LOG_HR_IF_MSG(E_FAIL, localResult != S_OK, "Failure adding relay port %d", addr.Ipv4.sin_port);
127
+ const int localResult = ModifyOpenPorts(c_eth0DeviceName, addr, protocol, allocate);
128
+ LOG_HR_IF_MSG(E_FAIL, localResult != S_OK, "Failure adding relay port %d", INETADDR_PORT(reinterpret_cast<const SOCKADDR*>(&addr)));
129
if (result == 0)
130
{
131
result = localResult;
@@ -238,8 +166,7 @@ int VirtioNetworking::ModifyOpenPorts(_In_ PCWSTR tag, _In_ const SOCKADDR_INET&
166
}
167
else
168
{
241
- wchar_t addrStr[16]; // "000.000.000.000" + null terminator
242
- RtlIpv4AddressToStringW(&addr.Ipv4.sin_addr, addrStr);
169
+ const auto addrStr = wsl::windows::common::string::SockAddrInetToWstring(addr);
170
portString += std::format(L";listen_addr={}", addrStr);
171
}
172
@@ -251,57 +178,128 @@ int VirtioNetworking::ModifyOpenPorts(_In_ PCWSTR tag, _In_ const SOCKADDR_INET&
178
179
void NETIOAPI_API_ VirtioNetworking::OnNetworkConnectivityChange(PVOID context, NL_NETWORK_CONNECTIVITY_HINT hint)
180
{
254
- static_cast<VirtioNetworking*>(context)->RefreshGuestConnection(hint);
181
+ static_cast<VirtioNetworking*>(context)->RefreshGuestConnection();
182
}
183
257
-void VirtioNetworking::RefreshGuestConnection(NL_NETWORK_CONNECTIVITY_HINT connectivityHint) noexcept
184
+void VirtioNetworking::RefreshGuestConnection() noexcept
185
try
186
{
260
- auto lock = m_lock.lock_exclusive();
261
- UpdateMtu();
187
+ // Query current networking information before acquiring the lock.
188
+ m_networkSettings = GetHostEndpointSettings();
189
263
- // Check for DNS changes and send update if needed.
264
- auto currentDns = networking::HostDnsInfo::GetDnsSettings(networking::DnsSettingsFlags::IncludeVpn);
265
- if (currentDns != m_trackedDnsSettings)
190
+ // TODO: Determine gateway MAC address
191
+ std::wstringstream device_options;
192
+ auto client_ip = m_networkSettings->PreferredIpAddress.AddressString;
193
+ if (!client_ip.empty())
194
{
267
- m_trackedDnsSettings = currentDns;
268
- SendDnsUpdate(currentDns);
195
+ if (device_options.tellp() > 0)
196
+ {
197
+ device_options << L";";
198
+ }
199
+ device_options << L"client_ip=" << client_ip;
200
}
270
-}
271
-CATCH_LOG();
201
273
-void VirtioNetworking::SendDnsUpdate(const networking::DnsInfo& dnsSettings)
274
-{
275
- hns::ModifyGuestEndpointSettingRequest<hns::DNS> notification{};
276
- notification.RequestType = hns::ModifyRequestType::Update;
277
- notification.ResourceType = hns::GuestEndpointResourceType::DNS;
278
- notification.Settings = networking::BuildDnsNotification(dnsSettings, m_dnsOptions);
279
- m_gnsChannel.SendHnsNotification(ToJsonW(notification).c_str(), m_adapterId);
280
-}
202
+ if (!m_networkSettings->MacAddress.empty())
203
+ {
204
+ if (device_options.tellp() > 0)
205
+ {
206
+ device_options << L";";
207
+ }
208
+ device_options << L"client_mac=" << m_networkSettings->MacAddress;
209
+ }
210
+
211
+ std::wstring default_route = m_networkSettings->GetBestGatewayAddressString();
212
+ if (!default_route.empty())
213
+ {
214
+ if (device_options.tellp() > 0)
215
+ {
216
+ device_options << L";";
217
+ }
218
+ device_options << L"gateway_ip=" << default_route;
219
+ }
220
+
221
+ const auto newDeviceOptions = device_options.str();
222
+
223
+ networking::DnsInfo currentDns{};
224
+ if (WI_IsFlagSet(m_flags, VirtioNetworkingFlags::DnsTunneling))
225
+ {
226
+ currentDns = networking::HostDnsInfo::GetDnsTunnelingSettings(default_route);
227
+ }
228
+ else
229
+ {
230
+ currentDns = networking::HostDnsInfo::GetDnsSettings(networking::DnsSettingsFlags::IncludeVpn);
231
+ }
232
282
-void VirtioNetworking::UpdateMtu()
283
-{
233
const auto minMtu = GetMinimumConnectedInterfaceMtu();
234
286
- // Only send the update if the MTU changed.
235
+ // Acquire the lock and perform device updates.
236
+ auto lock = m_lock.lock_exclusive();
237
+ if (newDeviceOptions != m_trackedDeviceOptions)
238
+ {
239
+ m_trackedDeviceOptions = newDeviceOptions;
240
+
241
+ // Add virtio net adapter to guest. If the adapter already exists update adapter state.
242
+ if (!m_adapterId.has_value())
243
+ {
244
+ m_adapterId = m_guestDeviceManager->AddGuestDevice(
245
+ VIRTIO_NET_DEVICE_ID, VIRTIO_NET_CLASS_ID, c_eth0DeviceName, nullptr, newDeviceOptions.c_str(), 0, m_userToken.get());
246
+ }
247
+ else
248
+ {
249
+ const auto server = m_guestDeviceManager->GetRemoteFileSystem(VIRTIO_NET_CLASS_ID, c_defaultDeviceTag);
250
+ if (server)
251
+ {
252
+ LOG_IF_FAILED(server->AddSharePath(c_eth0DeviceName, newDeviceOptions.c_str(), 0));
253
+ }
254
+ }
255
+
256
+ // N.B. The MAC address is advertised with the virtio device so doesn't need to be explicitly set.
257
+ hns::HNSEndpoint endpointProperties;
258
+ endpointProperties.ID = m_adapterId.value();
259
+ endpointProperties.IPAddress = m_networkSettings->PreferredIpAddress.AddressString;
260
+ endpointProperties.PrefixLength = m_networkSettings->PreferredIpAddress.PrefixLength;
261
+ m_gnsChannel.SendEndpointState(endpointProperties);
262
+
263
+ // Send the default route to GNS.
264
+ if (!default_route.empty())
265
+ {
266
+ wsl::shared::hns::Route route;
267
+ route.NextHop = default_route;
268
+ route.DestinationPrefix = LX_INIT_DEFAULT_ROUTE_PREFIX;
269
+ route.Family = AF_INET;
270
+
271
+ hns::ModifyGuestEndpointSettingRequest<hns::Route> request;
272
+ request.RequestType = hns::ModifyRequestType::Add;
273
+ request.ResourceType = hns::GuestEndpointResourceType::Route;
274
+ request.Settings = route;
275
+ m_gnsChannel.SendHnsNotification(ToJsonW(request).c_str(), m_adapterId.value());
276
+ }
277
+ }
278
+
279
+ // Send DNS update if needed.
280
+ if (currentDns != m_trackedDnsSettings)
281
+ {
282
+ m_trackedDnsSettings = currentDns;
283
+ hns::ModifyGuestEndpointSettingRequest<hns::DNS> notification{};
284
+ notification.RequestType = hns::ModifyRequestType::Update;
285
+ notification.ResourceType = hns::GuestEndpointResourceType::DNS;
286
+ notification.Settings = networking::BuildDnsNotification(currentDns, m_dnsOptions);
287
+ m_gnsChannel.SendHnsNotification(ToJsonW(notification).c_str(), m_adapterId.value());
288
+ }
289
+
290
+ // Send MTU update if needed.
291
if (minMtu && minMtu.value() != m_networkMtu)
292
{
293
m_networkMtu = minMtu.value();
290
-
294
hns::ModifyGuestEndpointSettingRequest<hns::NetworkInterface> notification{};
295
notification.ResourceType = hns::GuestEndpointResourceType::Interface;
296
notification.RequestType = hns::ModifyRequestType::Update;
297
notification.Settings.Connected = true;
298
notification.Settings.NlMtu = m_networkMtu;
296
-
297
- WSL_LOG(
298
- "VirtioNetworking::UpdateMtu",
299
- TraceLoggingValue(m_adapterId, "endpointId"),
300
- TraceLoggingValue(m_networkMtu, "virtioMtu"));
301
-
302
- m_gnsChannel.SendHnsNotification(ToJsonW(notification).c_str(), m_adapterId);
299
+ m_gnsChannel.SendHnsNotification(ToJsonW(notification).c_str(), m_adapterId.value());
300
}
301
}
302
+CATCH_LOG();
303
304
void VirtioNetworking::TraceLoggingRundown() noexcept
305
{
@@ -317,106 +315,3 @@ void VirtioNetworking::FillInitialConfiguration(LX_MINI_INIT_NETWORKING_CONFIGUR
315
message.EnableDhcpClient = false;
316
message.PortTrackerType = LX_MINI_INIT_PORT_TRACKER_TYPE::LxMiniInitPortTrackerTypeMirrored;
317
}
320
-
321
-std::optional<ULONGLONG> VirtioNetworking::FindVirtioInterfaceLuid(const SOCKADDR_INET& VirtioAddress, const NL_NETWORK_CONNECTIVITY_HINT& currentConnectivityHint)
322
-{
323
- constexpr ULONGLONG maxTimeToWaitMs = 10 * 1000;
324
- constexpr ULONG timeToSleepMs = 100;
325
- const auto startTickCount = GetTickCount64();
326
-
327
- NET_LUID VirtioLuid{};
328
- for (;;)
329
- {
330
- unique_address_table addressTable;
331
- THROW_IF_WIN32_ERROR(GetUnicastIpAddressTable(AF_INET, &addressTable));
332
- for (const auto& address : wil::make_range(addressTable.get()->Table, addressTable.get()->NumEntries))
333
- {
334
- if (VirtioAddress == address.Address)
335
- {
336
- VirtioLuid.Value = address.InterfaceLuid.Value;
337
- break;
338
- }
339
-
340
- WSL_LOG(
341
- "VirtioNetworking::FindVirtioInterfaceLuid [IP Address comparison mismatch]",
342
- TraceLoggingValue(wsl::windows::common::string::SockAddrInetToString(VirtioAddress).c_str(), "VirtioAddress"),
343
- TraceLoggingValue(
344
- wsl::windows::common::string::SockAddrInetToString(address.Address).c_str(), "enumeratedAddress"));
345
- }
346
-
347
- if (VirtioLuid.Value != 0)
348
- {
349
- break;
350
- }
351
-
352
- // give up if something is just broken and taking too long
353
- if (GetTickCount64() - startTickCount >= maxTimeToWaitMs)
354
- {
355
- break;
356
- }
357
- // else sleep and try again shortly
358
- Sleep(timeToSleepMs);
359
- // bail if connectivity on the host has completely changed
360
- NL_NETWORK_CONNECTIVITY_HINT latestConnectivityHint{};
361
- GetNetworkConnectivityHint(&latestConnectivityHint);
362
- if (latestConnectivityHint != currentConnectivityHint)
363
- {
364
- WSL_LOG("VirtioNetworking::FindVirtioInterfaceLuid [connectivity changed while waiting for the Virtio interface]");
365
- THROW_WIN32_MSG(ERROR_RETRY, "connectivity changed while waiting for the Virtio interface");
366
- }
367
- }
368
-
369
- if (VirtioLuid.Value == 0)
370
- {
371
- WSL_LOG(
372
- "VirtioNetworking::FindVirtioInterfaceLuid [IP address not found]",
373
- TraceLoggingValue(VirtioLuid.Value, "VirtioInterfaceLuid"),
374
- TraceLoggingValue(wsl::windows::common::string::SockAddrInetToString(VirtioAddress).c_str(), "VirtioIPAddress"));
375
- return {};
376
- }
377
-
378
- WSL_LOG(
379
- "VirtioNetworking::FindVirtioInterfaceLuid [waiting for Virtio interface to be connected]",
380
- TraceLoggingValue(VirtioLuid.Value, "VirtioInterfaceLuid"),
381
- TraceLoggingValue(wsl::windows::common::string::SockAddrInetToString(VirtioAddress).c_str(), "VirtioIPAddress"));
382
-
383
- bool ipv4Connected = false;
384
- for (;;)
385
- {
386
- unique_interface_table interfaceTable{};
387
- THROW_IF_WIN32_ERROR(::GetIpInterfaceTable(AF_UNSPEC, &interfaceTable));
388
- // we only track the IPv4 interface because we only Virtio IPv4 to the container
389
- for (auto index = 0ul; index < interfaceTable.get()->NumEntries; ++index)
390
- {
391
- const auto& ipInterface = interfaceTable.get()->Table[index];
392
- if (ipInterface.Family == AF_INET && !!ipInterface.Connected && ipInterface.InterfaceLuid.Value == VirtioLuid.Value)
393
- {
394
- ipv4Connected = true;
395
- break;
396
- }
397
- }
398
- if (ipv4Connected)
399
- {
400
- break;
401
- }
402
-
403
- // give up if something is just broken and taking too long
404
- if (GetTickCount64() - startTickCount >= maxTimeToWaitMs)
405
- {
406
- break;
407
- }
408
- // else sleep and try again shortly
409
- Sleep(timeToSleepMs);
410
- // bail if connectivity on the host has completely changed
411
- NL_NETWORK_CONNECTIVITY_HINT latestConnectivityHint{};
412
- GetNetworkConnectivityHint(&latestConnectivityHint);
413
- if (latestConnectivityHint != currentConnectivityHint)
414
- {
415
- WSL_LOG("VirtioNetworking::FindVirtioInterfaceLuid [connectivity changed while waiting for the Virtio interface]");
416
- THROW_WIN32_MSG(ERROR_RETRY, "connectivity changed while waiting for the Virtio interface");
417
- }
418
- }
419
-
420
- // return zero if it's not connected yet so we can retry the next cycle
421
- return ipv4Connected ? VirtioLuid.Value : std::optional<ULONGLONG>();
422
-}
src/windows/common/VirtioNetworking.h
+14
-11
@@ -10,10 +10,18 @@
10
11
namespace wsl::core {
12
13
+enum class VirtioNetworkingFlags
14
+{
15
+ None = 0x0,
16
+ LocalhostRelay = 0x1,
17
+ DnsTunneling = 0x2,
18
+};
19
+DEFINE_ENUM_FLAG_OPERATORS(VirtioNetworkingFlags);
20
+
21
class VirtioNetworking : public INetworkingEngine
22
{
23
public:
16
- VirtioNetworking(GnsChannel&& gnsChannel, bool enableLocalhostRelay, LPCWSTR dnsOptions, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken);
24
+ VirtioNetworking(GnsChannel&& gnsChannel, VirtioNetworkingFlags flags, LPCWSTR dnsOptions, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken);
25
~VirtioNetworking();
26
27
// Note: This class cannot be moved because m_networkNotifyHandle captures a 'this' pointer.
@@ -28,18 +36,13 @@ public:
36
void FillInitialConfiguration(LX_MINI_INIT_NETWORKING_CONFIGURATION& message) override;
37
void StartPortTracker(wil::unique_socket&& socket) override;
38
31
- void StartLegacyPortTracker(wil::unique_socket&& socket);
32
-
39
private:
40
static void NETIOAPI_API_ OnNetworkConnectivityChange(PVOID context, NL_NETWORK_CONNECTIVITY_HINT hint);
35
- static std::optional<ULONGLONG> FindVirtioInterfaceLuid(const SOCKADDR_INET& virtioAddress, const NL_NETWORK_CONNECTIVITY_HINT& currentConnectivityHint);
41
42
HRESULT HandlePortNotification(const SOCKADDR_INET& addr, int protocol, bool allocate) const noexcept;
43
int ModifyOpenPorts(_In_ PCWSTR tag, _In_ const SOCKADDR_INET& addr, _In_ int protocol, _In_ bool isOpen) const;
39
- void RefreshGuestConnection(NL_NETWORK_CONNECTIVITY_HINT hint) noexcept;
44
+ void RefreshGuestConnection() noexcept;
45
void SetupLoopbackDevice();
41
- void SendDnsUpdate(const networking::DnsInfo& dnsSettings);
42
- void UpdateMtu();
46
47
mutable wil::srwlock m_lock;
48
@@ -48,13 +51,13 @@ private:
51
GnsChannel m_gnsChannel;
52
std::optional<GnsPortTrackerChannel> m_gnsPortTrackerChannel;
53
std::shared_ptr<networking::NetworkSettings> m_networkSettings;
51
- bool m_enableLocalhostRelay;
54
+ VirtioNetworkingFlags m_flags = VirtioNetworkingFlags::None;
55
LPCWSTR m_dnsOptions = nullptr;
53
- GUID m_localhostAdapterId;
54
- GUID m_adapterId;
56
+ std::optional<GUID> m_localhostAdapterId;
57
+ std::optional<GUID> m_adapterId;
58
56
- std::optional<ULONGLONG> m_interfaceLuid;
59
ULONG m_networkMtu = 0;
60
+ std::wstring m_trackedDeviceOptions;
61
networking::DnsInfo m_trackedDnsSettings;
62
63
// Note: this field must be destroyed first to stop the callbacks before any other field is destroyed.
src/windows/service/exe/WslCoreVm.cpp
+6
-2
@@ -576,8 +576,10 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
576
}
577
else if (m_vmConfig.NetworkingMode == NetworkingMode::VirtioProxy)
578
{
579
+ wsl::core::VirtioNetworkingFlags flags = wsl::core::VirtioNetworkingFlags::None;
580
+ WI_SetFlagIf(flags, wsl::core::VirtioNetworkingFlags::LocalhostRelay, m_vmConfig.EnableLocalhostRelay);
581
m_networkingEngine = std::make_unique<wsl::core::VirtioNetworking>(
580
- std::move(gnsChannel), m_vmConfig.EnableLocalhostRelay, LX_INIT_RESOLVCONF_FULL_HEADER, m_guestDeviceManager, m_userToken);
582
+ std::move(gnsChannel), flags, LX_INIT_RESOLVCONF_FULL_HEADER, m_guestDeviceManager, m_userToken);
583
}
584
else if (m_vmConfig.NetworkingMode == NetworkingMode::Bridged)
585
{
@@ -1929,7 +1931,9 @@ bool WslCoreVm::InitializeDrvFsLockHeld(_In_ HANDLE UserToken)
1931
1932
bool WslCoreVm::IsDnsTunnelingSupported() const
1933
{
1932
- WI_ASSERT(m_vmConfig.NetworkingMode == NetworkingMode::Nat || m_vmConfig.NetworkingMode == NetworkingMode::Mirrored);
1934
+ WI_ASSERT(
1935
+ m_vmConfig.NetworkingMode == NetworkingMode::Nat || m_vmConfig.NetworkingMode == NetworkingMode::Mirrored ||
1936
+ m_vmConfig.NetworkingMode == NetworkingMode::VirtioProxy);
1937
1938
return SUCCEEDED_LOG(wsl::core::networking::DnsResolver::LoadDnsResolverMethods());
1939
}
test/linux/unit_tests/drvfs.c
-7
@@ -1422,13 +1422,6 @@ Return Value:
1422
1423
int Result;
1424
1425
- if (g_LxtFsInfo.FsType == LxtFsTypeVirtioFs)
1426
- {
1427
- LxtLogInfo("TODO: debug this test on virtiofs.");
1428
- Result = 0;
1429
- goto ErrorExit;
1430
- }
1431
-
1425
LxtCheckResult(LxtFsDeleteLoopCommon(DRVFS_DELETELOOP_PREFIX));
1426
1427
ErrorExit:
test/linux/unit_tests/fscommon.c
+2
-16
@@ -3405,13 +3405,6 @@ Return Value:
3405
3406
int Result;
3407
3408
- if (g_LxtFsInfo.FsType == LxtFsTypeVirtioFs)
3409
- {
3410
- LxtLogInfo("TODO: debug this test on virtiofs");
3411
- Result = 0;
3412
- goto ErrorExit;
3413
- }
3414
-
3408
LxtCheckResult(LxtFsDeleteLoopCommon(FS_DELETELOOP_TEST_DIR));
3409
3410
ErrorExit:
@@ -3777,16 +3770,9 @@ int FsCommonTestNoatimeFlag(PLXT_ARGS Args)
3770
// Plan 9 and virtiofs do not forward O_NOATIME to the server.
3771
//
3772
3780
- if (g_LxtFsInfo.FsType == LxtFsTypePlan9)
3781
- {
3782
- LxtLogInfo("Test not supported on Plan 9.");
3783
- Result = 0;
3784
- goto ErrorExit;
3785
- }
3786
-
3787
- if (g_LxtFsInfo.FsType == LxtFsTypeVirtioFs)
3773
+ if (g_LxtFsInfo.FsType == LxtFsTypePlan9 || g_LxtFsInfo.FsType == LxtFsTypeVirtioFs)
3774
{
3789
- LxtLogInfo("Test not supported on virtiofs.");
3775
+ LxtLogInfo("This test is not supported for plan9 or virtiofs.");
3776
Result = 0;
3777
goto ErrorExit;
3778
}
test/windows/NetworkTests.cpp
+3
-30
@@ -178,33 +178,6 @@ class NetworkTests
178
friend class BridgedTests;
179
friend class VirtioProxyTests;
180
181
- static std::wstring SockaddrToString(const SOCKADDR_INET* sockAddr)
182
- {
183
- constexpr auto ipv4AddressStringLength = 16;
184
- constexpr auto ipv6AddressStringLength = 48;
185
-
186
- std::wstring address(std::max(ipv4AddressStringLength, ipv6AddressStringLength), L'\0');
187
-
188
- switch (sockAddr->si_family)
189
- {
190
- case AF_INET:
191
- {
192
- RtlIpv4AddressToStringW(&sockAddr->Ipv4.sin_addr, address.data());
193
- break;
194
- }
195
- case AF_INET6:
196
- {
197
- RtlIpv6AddressToStringW(&sockAddr->Ipv6.sin6_addr, address.data());
198
- break;
199
- }
200
- default:
201
- break;
202
- }
203
-
204
- address.resize(std::wcslen(address.data()));
205
- return address;
206
- }
207
-
181
struct IpAddress
182
{
183
std::wstring Address;
@@ -243,7 +216,7 @@ class NetworkTests
216
}
217
}
218
246
- return SockaddrToString(address) + L"/" + std::to_wstring(PrefixLength);
219
+ return wsl::windows::common::string::SockAddrInetToWstring(*address) + L"/" + std::to_wstring(PrefixLength);
220
}
221
};
222
@@ -812,7 +785,7 @@ class NetworkTests
785
}
786
else
787
{
815
- LogSkipped("Host does not have IPv4 internet connectivity. Skipping IPv4 DNS tests.");
788
+ LogInfo("Host does not have IPv4 internet connectivity. Skipping IPv4 DNS tests.");
789
}
790
791
if (HostHasInternetConnectivity(AF_INET6))
@@ -823,7 +796,7 @@ class NetworkTests
796
}
797
else
798
{
826
- LogSkipped("Host does not have IPv6 internet connectivity. Skipping IPv6 DNS tests.");
799
+ LogInfo("Host does not have IPv6 internet connectivity. Skipping IPv6 DNS tests.");
800
}
801
}
802