Skip to content
Open
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
e5b2d48
[vm-factory] Fetch networks supported by applevz
sharder996 Feb 23, 2026
4e43e5f
[vm] Bridged network via applevz framework
sharder996 Feb 23, 2026
ab29092
[applevz] Add file for housing vmnet code
sharder996 Mar 3, 2026
05d0daa
[vmnet] Create struct for custom network interface
sharder996 Mar 3, 2026
6f82b40
[applevz] Refine interface for vmnet relays
sharder996 Mar 17, 2026
25e8255
[applevz] Translate AppleVZ usage to vmnet
sharder996 Mar 17, 2026
584476c
[packaging] Remove networking entitlement
sharder996 Mar 17, 2026
3ee53aa
[applevz] Assign MAC address to bridged interface
sharder996 Mar 21, 2026
89efd8a
[vmnet] Rework VmnetRelay struct
sharder996 Mar 21, 2026
243f24a
[vmnet] Mock up vmnet network interface creation
sharder996 Mar 22, 2026
c0b58e3
[vmnet] Start vmnet interface impl
sharder996 Mar 22, 2026
b52e8e5
[vmnet] DGRAM socket creation
sharder996 Mar 22, 2026
9c09d51
[vmnet] Start relay communication
sharder996 Mar 22, 2026
52ab8ef
[vmnet] Don't generate UUIDs
sharder996 Mar 23, 2026
4ab411e
[vmnet] Log vmnet destruction process
sharder996 Mar 23, 2026
d24686b
[vmnet] Add performance improvements
sharder996 Mar 24, 2026
d2b4d9c
[vmnet] Credit original authors
sharder996 Mar 24, 2026
a3cae43
[applevz] Add some testing for VM factory
sharder996 Mar 24, 2026
bbc4484
[vmnet] Use a bit more idiomatic C++
sharder996 Mar 26, 2026
70f2a4a
[vmnet] Organize buffers into struct
sharder996 Apr 6, 2026
3b706e7
[vmnet] Convert to chrono units
sharder996 Apr 6, 2026
ba96f91
[vmnet] Symmetrize forwarding loops
sharder996 Apr 6, 2026
9eb4b90
[vmnet] Directly return std::array
sharder996 Apr 6, 2026
6c462db
[vmnet] Simplify loop
sharder996 Apr 6, 2026
0feafc9
[bridge] Apply code suggestions
sharder996 Apr 6, 2026
72f75f9
[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 @@ -67,6 +67,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 @@ -47,8 +47,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