How Container Integrates with the vmnet Framework for Container Networking
Container integrates with the vmnet framework through an XPC helper service that translates high-level network configurations into macOS vmnet API calls, creating NAT or host-only networks and serializing the network references for container runtime attachment.
The apple/container project implements container networking on macOS by leveraging the native vmnet framework, providing NAT and host-only connectivity for Linux containers. This integration bridges the gap between high-level network management commands and low-level macOS virtualization APIs through a carefully architected XPC service. Understanding this container vmnet framework integration reveals how the project achieves performant, native networking without requiring third-party kernel extensions.
Architecture Overview
The container vmnet framework integration follows a three-layer architecture that separates user commands from privileged virtualization operations:
- CLI Layer: Parses
container networkcommands and constructsNetworkConfigurationobjects inSources/ContainerCommands/Network/NetworkCreate.swift - XPC Helper Layer: The
container-network-vmnetservice receives configurations via theContainerNetworkServerAPI and manages vmnet network lifecycle - Runtime Layer: The
container-runtime-linuxhelper deserializes network references and creates container interfaces
This design ensures that privileged vmnet operations remain isolated within the XPC service while the runtime handles container-specific network attachment.
Network Creation and Configuration Flow
CLI Network Definition
When a user executes container network create, the CLI builds a NetworkConfiguration structure that specifies the operating mode (NAT or host-only), IPv4/IPv6 subnets, labels, and the plugin name (defaulting to container-network-vmnet). In Sources/ContainerCommands/Network/NetworkCreate.swift, this configuration is validated and passed to the XPC helper via the ContainerNetworkServer module.
XPC Helper Translation
The container-network-vmnet helper implements the Network protocol defined in the ContainerNetworkServer target. In Sources/Plugins/NetworkVmnet/NetworkVmnetHelper.swift, the helper receives the configuration and instantiates ReservedVmnetNetwork to handle the low-level vmnet operations.
vmnet Network Initialization
The ReservedVmnetNetwork class in Sources/Services/NetworkVmnet/Server/ReservedVmnetNetwork.swift manages the direct interaction with the vmnet framework.
Operating Mode Selection
The helper selects the appropriate vmnet operating mode based on the configuration:
.VMNET_SHARED_MODE: Used for NAT networking (default), allowing containers to access external networks through the host.VMNET_HOST_MODE: Used for host-only networking when the--internalflag is specified
Subnet Configuration and DHCP Disablement
The implementation disables DHCP since the helper manages its own address allocation:
// ReservedVmnetNetwork.swift - Disabling DHCP
// Lines 16-18
config.ipv4_disable_dhcp = true
config.ipv6_disable_dhcp = true
When subnets are provided, the helper populates the vmnet configuration using native API calls:
// Lines 30-34
if let subnet = ipv4Subnet {
guard vmnet_network_configuration_set_ipv4_subnet(&config, subnet) == VMNET_SUCCESS else {
throw error
}
}
// Lines 40-44
if let prefix = ipv6Prefix {
guard vmnet_network_configuration_set_ipv6_prefix(&config, prefix) == VMNET_SUCCESS else {
throw error
}
}
Network Creation and Reference Storage
After configuration, the network is created and stored:
// Lines 54-58
var status = vmnet_network_status_t()
let networkRef = vmnet_network_create(&config, &status)
guard status == VMNET_SUCCESS else {
throw error
}
self.vmnetNetworkRef = networkRef
Runtime Attachment and Interface Binding
Serialization via vmnet_network_copy_serialization
When containers need to attach to the network, the helper serializes the vmnet_network_ref into an XPC message that can be transferred to the runtime:
// ReservedVmnetNetwork.swift - Lines 92-99
var serialization = vmnet_network_serialization_t()
var serializationLength = 0
guard vmnet_network_copy_serialization(vmnetNetworkRef, &serialization, &serializationLength) == VMNET_SUCCESS else {
throw error
}
// Attach to XPC message for runtime transfer
Deserialization and NATNetworkInterface Creation
In Sources/Services/RuntimeLinux/Server/NonisolatedInterfaceStrategy.swift, the runtime helper receives the XPC data and reconstructs the network reference:
// Lines 35-53
let networkRef = vmnet_network_create_with_serialization(additionalData.underlying, &status)
guard status == VMNET_SUCCESS else {
throw error
}
let interface = NATNetworkInterface(
ipv4Address: attachment.ipv4Address,
ipv4Gateway: attachment.ipv4Gateway,
reference: networkRef,
macAddress: attachment.macAddress,
mtu: attachment.mtu ?? 1280
)
This NATNetworkInterface encapsulates the container's IPv4 address, gateway, MAC address, and the underlying vmnet reference.
Address Allocation and Network Lifecycle
The helper allocates IP addresses from the configured subnet automatically. In NAT mode, the first container receives the gateway address while subsequent containers receive sequential IPs. For host-only mode, the same allocation mechanism applies without NAT translation.
The network lifecycle supports inspect and stop operations via the ContainerNetworkServer API, reporting active subnets and gateway information back to the CLI.
Practical Examples
Create a NAT network using the default vmnet plugin:
container network create \
--label env=dev \
--option mtu=1500 \
my-net
Create a host-only network with specific subnet:
container network create \
--internal \
--subnet 10.0.0.0/24 \
host-only-net
Inspect network configuration:
container network inspect my-net
Platform Requirements and Limitations
The vmnet framework integration requires macOS 26+ for full functionality, marked with @available(macOS 26, *) in the source. On macOS 15, the framework supports only isolated host-only networks, reflecting the API limitations documented in the technical overview.
Summary
- Container vmnet framework integration relies on an XPC helper service (
container-network-vmnet) to proxy vmnet operations from the CLI to the macOS kernel - The
ReservedVmnetNetworkclass configures vmnet usingVMNET_SHARED_MODEfor NAT orVMNET_HOST_MODEfor host-only networking, always disabling DHCP - Network references are serialized using
vmnet_network_copy_serializationand deserialized in the runtime viavmnet_network_create_with_serializationto createNATNetworkInterfaceinstances - IP address allocation and gateway assignment are managed by the helper, not the vmnet DHCP server
- Full functionality requires macOS 26 or later, with limited host-only support on macOS 15
Frequently Asked Questions
What is the vmnet framework and why does Container use it?
The vmnet framework is Apple's native macOS API for creating virtual networks without kernel extensions. Container uses it to provide high-performance, NAT, and host-only networking for Linux containers while maintaining compatibility with macOS virtualization standards and security models.
What is the difference between NAT and host-only networking modes in Container?
NAT mode (VMNET_SHARED_MODE) allows containers to access external networks through the host's internet connection, while host-only mode (VMNET_HOST_MODE) creates an isolated network where containers can only communicate with the host and other containers on the same network. The mode is selected via the --internal flag during network creation.
How does the XPC helper service improve security in Container's vmnet integration?
The XPC helper isolates privileged vmnet operations (vmnet_network_create, interface configuration) into a separate service (container-network-vmnet) that runs with elevated privileges, while the main CLI and runtime operate with reduced permissions. This follows the principle of least privilege, ensuring that only the minimal necessary code interacts with low-level networking APIs.
Why does Container require macOS 26+ for full vmnet functionality?
The complete vmnet API, including support for NAT networking and network serialization, requires macOS 26 or later. Earlier versions (macOS 15) only support isolated host-only networks without the serialization capabilities needed for the full container runtime integration, as implemented in ReservedVmnetNetwork.swift and NonisolatedInterfaceStrategy.swift.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →