@samitouri / QOSAMI-WSL / commits / 218b71be

Resolve and pass gateway MAC address to virtio net device (#14386)

Use ResolveIpNetEntry2 to look up the host gateway's MAC address and pass it as the gateway_mac device option to the virtio net adapter. This allows the guest to see the real gateway MAC instead of the default consomme address. Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>

Ben Hillis committed Mar 9, 2026 at 14:51 UTC 218b71be6717c977f17eb7b70a1747a60661d51f
3 files changed +46 -21
src/windows/common/VirtioNetworking.cpp
+9 -21
@@ -172,32 +172,20 @@ try
172 // Query current networking information before acquiring the lock.
173 auto networkSettings = GetHostEndpointSettings();
174
175 - // TODO: Determine gateway MAC address
175 std::wstring device_options;
177 - auto client_ip = networkSettings->PreferredIpAddress.AddressString;
178 - if (!client_ip.empty())
179 - {
180 - device_options += L"client_ip=" + client_ip;
181 - }
182 -
183 - if (!networkSettings->MacAddress.empty())
184 - {
185 - if (!device_options.empty())
176 + auto appendOption = [&device_options](std::wstring_view key, std::wstring_view value) {
177 + if (!value.empty())
178 {
187 - device_options += L';';
179 + std::format_to(std::back_inserter(device_options), L"{}{}={}", device_options.empty() ? L"" : L";", key, value);
180 }
189 - device_options += L"client_mac=" + networkSettings->MacAddress;
190 - }
181 + };
182 +
183 + appendOption(L"client_ip", networkSettings->PreferredIpAddress.AddressString);
184 + appendOption(L"client_mac", networkSettings->MacAddress);
185
186 std::wstring default_route = networkSettings->GetBestGatewayAddressString();
193 - if (!default_route.empty())
194 - {
195 - if (!device_options.empty())
196 - {
197 - device_options += L';';
198 - }
199 - device_options += L"gateway_ip=" + default_route;
200 - }
187 + appendOption(L"gateway_ip", default_route);
188 + appendOption(L"gateway_mac", networkSettings->GetBestGatewayMacAddress());
189
190 networking::DnsInfo currentDns{};
191 if (WI_IsFlagSet(m_flags, VirtioNetworkingFlags::DnsTunneling))
src/windows/common/WslCoreNetworkEndpointSettings.cpp
+35
@@ -94,3 +94,38 @@ std::shared_ptr<wsl::core::networking::NetworkSettings> wsl::core::networking::G
94 return std::make_shared<NetworkSettings>(
95 bestInterface->NetworkGuid, address, route, macAddress, bestInterface->IfIndex, bestInterface->IfType);
96 }
97 +
98 +std::wstring wsl::core::networking::NetworkSettings::GetBestGatewayMacAddress() const
99 +{
100 + auto gatewayAddress = GetBestGatewayAddress();
101 + if (gatewayAddress.si_family != AF_INET)
102 + {
103 + return {};
104 + }
105 +
106 + MIB_IPNET_ROW2 ipNetRow{};
107 + ipNetRow.Address = gatewayAddress;
108 + ipNetRow.InterfaceIndex = InterfaceIndex;
109 +
110 + const auto result = ResolveIpNetEntry2(&ipNetRow, nullptr);
111 + if (result != NO_ERROR)
112 + {
113 + LOG_HR_MSG(HRESULT_FROM_WIN32(result), "Failed to resolve gateway MAC address");
114 + return {};
115 + }
116 +
117 + if (ipNetRow.PhysicalAddressLength != 6)
118 + {
119 + return {};
120 + }
121 +
122 + return wsl::shared::string::FormatMacAddress(
123 + wsl::shared::string::MacAddress{
124 + ipNetRow.PhysicalAddress[0],
125 + ipNetRow.PhysicalAddress[1],
126 + ipNetRow.PhysicalAddress[2],
127 + ipNetRow.PhysicalAddress[3],
128 + ipNetRow.PhysicalAddress[4],
129 + ipNetRow.PhysicalAddress[5]},
130 + L'-');
131 +}
src/windows/common/WslCoreNetworkEndpointSettings.h
+2
@@ -318,6 +318,8 @@ struct NetworkSettings
318 return {};
319 }
320
321 + std::wstring GetBestGatewayMacAddress() const;
322 +
323 std::wstring IpAddressesString() const
324 {
325 return std::accumulate(std::begin(IpAddresses), std::end(IpAddresses), std::wstring{}, [](const std::wstring& prev, const auto& addr) {