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