virtionet: send runtime updates to network device (#41263)
* net: virtionet: send runtime updates to network device * remove BOM * Avoid redundant virtio-net updates Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Brian Perkins <bperkins@ntdev.microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Brian Perkins committed
Aug 6, 2026 at 09:41 UTC
bf791e06661bf2ad56fe8c5d8cd7c5f56154205f
3 files changed
+39
-5
packages.config
+1
-1
@@ -19,7 +19,7 @@
19
<package id="Microsoft.WSL.bsdtar" version="0.0.2-2" />
20
<package id="Microsoft.WSL.Dependencies.amd64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" />
21
<package id="Microsoft.WSL.Dependencies.arm64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" />
22
- <package id="Microsoft.WSL.DeviceHost" version="1.2.54-0" />
22
+ <package id="Microsoft.WSL.DeviceHost" version="1.2.56-0" />
23
<package id="Microsoft.WSL.Kernel" version="6.18.35.2-1" targetFramework="native" />
24
<package id="Microsoft.WSL.LinuxSdk" version="1.23.0" targetFramework="native" />
25
<package id="Microsoft.WSL.TestData" version="0.5.0" />
src/windows/common/ConsommeNetworking.cpp
+36
-4
@@ -67,6 +67,28 @@ IpAddress ToIpAddress(const SOCKADDR_INET& address)
67
return result;
68
}
69
70
+bool AreEqual(const IpAddress& left, const IpAddress& right)
71
+{
72
+ return left.family == right.family && std::equal(std::begin(left.bytes), std::end(left.bytes), std::begin(right.bytes));
73
+}
74
+
75
+bool AreEqual(const std::vector<IpAddress>& left, const std::vector<IpAddress>& right)
76
+{
77
+ return std::ranges::equal(
78
+ left, right, [](const auto& leftAddress, const auto& rightAddress) { return AreEqual(leftAddress, rightAddress); });
79
+}
80
+
81
+bool AreEqual(const WslVirtioNetConfig& left, const WslVirtioNetConfig& right)
82
+{
83
+ return left.clientIp.value == right.clientIp.value && left.hasClientIpv6 == right.hasClientIpv6 &&
84
+ std::equal(std::begin(left.clientIpv6.bytes), std::end(left.clientIpv6.bytes), std::begin(right.clientIpv6.bytes)) &&
85
+ std::equal(std::begin(left.clientMac.bytes), std::end(left.clientMac.bytes), std::begin(right.clientMac.bytes)) &&
86
+ left.gatewayIp.value == right.gatewayIp.value &&
87
+ std::equal(std::begin(left.gatewayMac.bytes), std::end(left.gatewayMac.bytes), std::begin(right.gatewayMac.bytes)) &&
88
+ std::equal(std::begin(left.gatewayMacIpv6.bytes), std::end(left.gatewayMacIpv6.bytes), std::begin(right.gatewayMacIpv6.bytes)) &&
89
+ left.netmask.value == right.netmask.value;
90
+}
91
+
92
std::vector<IpAddress> ToIpAddresses(const DnsInfo& dns)
93
{
94
std::vector<IpAddress> result;
@@ -316,12 +338,13 @@ void ConsommeNetworking::RefreshGuestConnection()
338
}
339
340
const auto minMtu = GetMinimumConnectedInterfaceMtu();
319
- const auto virtioNetConfig = BuildVirtioNetConfig(networkSettings, WI_IsFlagSet(m_flags, ConsommeNetworkingFlags::Ipv6));
341
+ auto virtioNetConfig = BuildVirtioNetConfig(networkSettings, WI_IsFlagSet(m_flags, ConsommeNetworkingFlags::Ipv6));
342
+ auto nameservers = ToIpAddresses(currentDns);
343
344
// Acquire the lock and perform device updates.
345
auto lock = m_lock.lock_exclusive();
346
324
- // Add virtio net adapter to guest. Subsequent address/route/DNS changes are sent through GNS notifications below.
347
+ // Add the virtio net adapter to the guest, or update its runtime configuration.
348
if (!m_adapterId.has_value())
349
{
350
WSL_LOG(
@@ -330,9 +353,18 @@ void ConsommeNetworking::RefreshGuestConnection()
353
TraceLoggingValue(networkSettings->PreferredIpAddress.PrefixLength, "PrefixLength"),
354
TraceLoggingValue(default_route.c_str(), "GatewayIp"),
355
TraceLoggingValue(networkSettings->PreferredIpv6Address.AddressString.c_str(), "ClientIpv6"));
333
- m_adapterId =
334
- m_guestDeviceManager->AddVirtioNetDevice(c_eth0DeviceName, virtioNetConfig, ToIpAddresses(currentDns), m_userToken.get());
356
+ m_adapterId = m_guestDeviceManager->AddVirtioNetDevice(c_eth0DeviceName, virtioNetConfig, nameservers, m_userToken.get());
357
}
358
+ else if (!m_virtioNetConfig.has_value() || !AreEqual(m_virtioNetConfig.value(), virtioNetConfig) || !AreEqual(m_virtioNetNameservers, nameservers))
359
+ {
360
+ IpAddress emptyNameserver{};
361
+ auto* nameserversData = nameservers.empty() ? &emptyNameserver : nameservers.data();
362
+ const auto device = m_guestDeviceManager->GetVirtioNetDevice(c_eth0DeviceName);
363
+ THROW_IF_FAILED(device->Update(&virtioNetConfig, gsl::narrow_cast<UINT32>(nameservers.size()), nameserversData));
364
+ }
365
+
366
+ m_virtioNetConfig = virtioNetConfig;
367
+ m_virtioNetNameservers = std::move(nameservers);
368
369
UpdateIpv4Address(networkSettings->PreferredIpAddress);
370
if (WI_IsFlagSet(m_flags, ConsommeNetworkingFlags::Ipv6))
src/windows/common/ConsommeNetworking.h
+2
@@ -70,6 +70,8 @@ private:
70
LPCWSTR m_dnsOptions = nullptr;
71
std::optional<GUID> m_localhostAdapterId;
72
std::optional<GUID> m_adapterId;
73
+ std::optional<WslVirtioNetConfig> m_virtioNetConfig;
74
+ std::vector<IpAddress> m_virtioNetNameservers;
75
76
ULONG m_networkMtu = 0;
77
networking::EndpointIpAddress m_trackedIpv4Address{};