Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5e0b2b7
[vm-factory] Fetch networks supported by applevz
sharder996 Feb 23, 2026
84f334c
[vm] Bridged network via applevz framework
sharder996 Feb 23, 2026
b7c84d5
[applevz] Add file for housing vmnet code
sharder996 Mar 3, 2026
a58f8a9
[vmnet] Create struct for custom network interface
sharder996 Mar 3, 2026
9213909
[applevz] Refine interface for vmnet relays
sharder996 Mar 17, 2026
af09171
[applevz] Translate AppleVZ usage to vmnet
sharder996 Mar 17, 2026
dbf85e4
[packaging] Remove networking entitlement
sharder996 Mar 17, 2026
0589559
[applevz] Assign MAC address to bridged interface
sharder996 Mar 21, 2026
819e7ab
[vmnet] Rework VmnetRelay struct
sharder996 Mar 21, 2026
c5f591e
[vmnet] Mock up vmnet network interface creation
sharder996 Mar 22, 2026
dfa8244
[vmnet] Start vmnet interface impl
sharder996 Mar 22, 2026
e0dbe07
[vmnet] DGRAM socket creation
sharder996 Mar 22, 2026
dab0d6d
[vmnet] Start relay communication
sharder996 Mar 22, 2026
e8ac418
[vmnet] Don't generate UUIDs
sharder996 Mar 23, 2026
a527bb1
[vmnet] Log vmnet destruction process
sharder996 Mar 23, 2026
2450ea4
[vmnet] Add performance improvements
sharder996 Mar 24, 2026
9c93211
[vmnet] Credit original authors
sharder996 Mar 24, 2026
ca99b61
[applevz] Add some testing for VM factory
sharder996 Mar 24, 2026
842561a
[vmnet] Use a bit more idiomatic C++
sharder996 Mar 26, 2026
09c94c5
[vmnet] Organize buffers into struct
sharder996 Apr 6, 2026
e3e90a7
[vmnet] Convert to chrono units
sharder996 Apr 6, 2026
1b10902
[vmnet] Symmetrize forwarding loops
sharder996 Apr 6, 2026
434af6e
[vmnet] Directly return std::array
sharder996 Apr 6, 2026
7ee27b6
[vmnet] Simplify loop
sharder996 Apr 6, 2026
971399f
[bridge] Apply code suggestions
sharder996 Apr 6, 2026
825cf47
[tests] Test vm cloning
sharder996 Apr 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/platform/backends/applevz/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@ add_library(applevz_backend STATIC
applevz_bridge.mm
applevz_wrapper.cpp
applevz_utils.mm
applevz_vmnet.mm
)

set_source_files_properties(
applevz_bridge.mm
applevz_utils.mm
applevz_vmnet.mm
PROPERTIES
LANGUAGE OBJCXX
COMPILE_FLAGS "-fobjc-arc"
)

find_library(FOUNDATION_FRAMEWORK Foundation REQUIRED)
find_library(VIRTUALIZATION_FRAMEWORK Virtualization REQUIRED)
find_library(VMNET_FRAMEWORK vmnet REQUIRED)

target_link_libraries(applevz_backend
PUBLIC
Expand All @@ -43,4 +46,5 @@ target_link_libraries(applevz_backend
daemon
${FOUNDATION_FRAMEWORK}
${VIRTUALIZATION_FRAMEWORK}
${VMNET_FRAMEWORK}
Qt6::Core)
4 changes: 4 additions & 0 deletions src/platform/backends/applevz/applevz_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#pragma once

#include <applevz/cf_error.h>
#include <multipass/network_interface_info.h>
#include <multipass/virtual_machine_description.h>

#include <fmt/format.h>
Expand Down Expand Up @@ -63,6 +64,9 @@ bool can_stop(const VMHandle& vm_handle);
bool can_request_stop(const VMHandle& vm_handle);

bool is_supported();

// Networking
std::vector<NetworkInterfaceInfo> bridged_network_interfaces();
} // namespace multipass::applevz

template <>
Expand Down
56 changes: 49 additions & 7 deletions src/platform/backends/applevz/applevz_bridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include <applevz/applevz_bridge.h>
#include <applevz/applevz_vmnet.h>

#include <CoreFoundation/CoreFoundation.h>
#include <Foundation/Foundation.h>
Expand All @@ -29,13 +30,16 @@
#include <QString>
#include <QUrl>

#include <cassert>

namespace multipass::applevz
{
struct VirtualMachineHandle
{
std::shared_ptr<void> vm; // Ownership transfer of VZVirtualMachine*
dispatch_queue_t queue; // Dispatch queue for VM operations
uint64_t id; // Unique VM ID
std::shared_ptr<void> vm; // Ownership transfer of VZVirtualMachine*
dispatch_queue_t queue; // Dispatch queue for VM operations
uint64_t id; // Unique VM ID
std::vector<VmnetRelayHandle> relays; // vmnet relay lifetime handles
};
} // namespace multipass::applevz

Expand Down Expand Up @@ -172,18 +176,40 @@ CFError init_with_configuration(const multipass::VirtualMachineDescription& desc
[[VZVirtioEntropyDeviceConfiguration alloc] init];
config.entropyDevices = @[ entropy ];

// Network device
// Network devices
// Primary NAT interface
NSMutableArray<VZNetworkDeviceConfiguration*>* networkDevices = [NSMutableArray array];

VZVirtioNetworkDeviceConfiguration* netDevice =
[[VZVirtioNetworkDeviceConfiguration alloc] init];

VZNATNetworkDeviceAttachment* natAttachment = [[VZNATNetworkDeviceAttachment alloc] init];
netDevice.attachment = natAttachment;

VZMACAddress* mac =
[[VZMACAddress alloc] initWithString:nsstring_from_stdstring(desc.default_mac_address)];
[netDevice setMACAddress:mac];
[networkDevices addObject:netDevice];

// Extra bridged interfaces
std::vector<VmnetRelayHandle> relays;
for (const auto& extra : desc.extra_interfaces)
{
VmnetBridge bridge = create_vmnet_bridge(extra.id);
Comment thread
jimporter marked this conversation as resolved.

VZVirtioNetworkDeviceConfiguration* bridgedDevice =
[[VZVirtioNetworkDeviceConfiguration alloc] init];
bridgedDevice.attachment = bridge.attachment;
VZMACAddress* bridgedMac = [[VZMACAddress alloc]
initWithString:[NSString stringWithCString:extra.mac_address.c_str()
encoding:NSUTF8StringEncoding]];
[bridgedDevice setMACAddress:bridgedMac];

[networkDevices addObject:bridgedDevice];

relays.push_back(std::move(bridge.relay));
Comment thread
jimporter marked this conversation as resolved.
}

config.networkDevices = @[ netDevice ];
config.networkDevices = networkDevices;

// Memory balloon device
VZVirtioTraditionalMemoryBalloonDeviceConfiguration* balloon =
Expand All @@ -197,7 +223,7 @@ CFError init_with_configuration(const multipass::VirtualMachineDescription& desc
}

out_handle = std::make_shared<VirtualMachineHandle>();

out_handle->relays = std::move(relays);
out_handle->id = vmIDCounter.fetch_add(1, std::memory_order_relaxed);

// Create dispatch queue
Expand Down Expand Up @@ -306,4 +332,20 @@ bool is_supported()
{
return [VZVirtualMachine isSupported];
}

std::vector<NetworkInterfaceInfo> bridged_network_interfaces()
{
std::vector<NetworkInterfaceInfo> result;

for (VZBridgedNetworkInterface* iface in [VZBridgedNetworkInterface networkInterfaces])
{
result.emplace_back(/* id = */ iface.identifier.UTF8String,
/* type = */ "N/A",
/* description = */ iface.localizedDisplayName
? std::string(iface.localizedDisplayName.UTF8String)
: iface.identifier.UTF8String);
}

return result;
}
} // namespace multipass::applevz
10 changes: 10 additions & 0 deletions src/platform/backends/applevz/applevz_virtual_machine_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ void AppleVZVirtualMachineFactory::remove_resources_for_impl(const std::string&
{
}

std::vector<NetworkInterfaceInfo> AppleVZVirtualMachineFactory::networks() const
{
return MP_APPLEVZ.bridged_network_interfaces();
}

std::string AppleVZVirtualMachineFactory::create_bridge_with(const NetworkInterfaceInfo& interface)
{
return interface.id;
}

VirtualMachine::UPtr AppleVZVirtualMachineFactory::clone_vm_impl(
const std::string& /*source_vm_name*/,
const multipass::VMSpecs& /*src_vm_specs*/,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@ class AppleVZVirtualMachineFactory final : public BaseVirtualMachineFactory
return "applevz";
};

std::vector<NetworkInterfaceInfo> networks() const override;

protected:
void remove_resources_for_impl(const std::string& name) override;
std::string create_bridge_with(const NetworkInterfaceInfo& interface) override;

private:
VirtualMachine::UPtr clone_vm_impl(const std::string& source_vm_name,
Expand Down
38 changes: 38 additions & 0 deletions src/platform/backends/applevz/applevz_vmnet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (C) Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#pragma once

#include <Virtualization/Virtualization.h>

#include <memory>

namespace multipass::applevz
{

// Opaque handle whose lifetime must exceed that of the attachment it was created with.
using VmnetRelayHandle = std::shared_ptr<void>;

struct VmnetBridge
{
VZFileHandleNetworkDeviceAttachment* attachment;
VmnetRelayHandle relay;
};

VmnetBridge create_vmnet_bridge(const std::string& physical_iface);

} // namespace multipass::applevz
Loading
Loading