vmnet_network_ref loses its DHCP reservations and port-forwarding rules when its last interface leaves

I'm using the macOS 26 vmnet network API with Virtualization framework (vmnet_network_create + VZVmnetNetworkDeviceAttachment) and giving each VM a stable address with vmnet_network_configuration_add_dhcp_reservation, plus creation-time rules from vmnet_network_configuration_add_port_forwarding_rule.

Both work on the network's first run. But if the network's last interface leaves while I still hold the vmnet_network_ref, then the next interface start brings the network back without its reservations or forwarding rules. The subnet and gateway are kept.

How it shows up in practice: a VM that is the only guest on its network gets restarted from inside the guest. Virtualization framework removes and re-adds the VM's vmnet interface about 1 s apart, with no delegate callback. That's enough to stop and restart the network, and the guest comes back on a dynamic lease with its forwarded ports refused.

Minimal repro, no VM needed:

  1. Create a configuration in VMNET_SHARED_MODE with set_ipv4_subnet, one add_dhcp_reservation and one add_port_forwarding_rule, then call vmnet_network_create.
  2. vmnet_interface_start_with_network. InternetSharing logs port forwarding enabled …, and /etc/bootptab contains the reservation.
  3. vmnet_stop_interface. InternetSharing logs no internal interface left, stopping network → reset to idle, and /etc/bootptab is emptied.
  4. vmnet_interface_start_with_network again on the same, still-retained ref. InternetSharing logs has been started with no port forwarding enabled line, and /etc/bootptab is never rewritten. The forwarded port is refused.
  5. Control: release the ref, call vmnet_network_create again from the same configuration, and start an interface. The reservation and the rule are both back.

Reproduced on macOS 27.0 (26A428) and (with a minimal vmnet only test, no actual VM) on macOS 26.6.2 (25G83).

This seems to contradict the documentation for vmnet_network_create: "The lifetime of such reservation is the same as that of vmnet_network_ref."

A related issue: vmnet_interface_add_ip_port_forwarding_rule and its remove and get counterparts return VMNET_FAILURE synchronously on an interface started with vmnet_interface_start_with_network. The same calls work on a vmnet_start_interface interface. The add_port_forwarding_rule documentation points to those calls for managing rules after start, so there's no way to put a rule back after the restart.

The same "torn down on last detach while the ref lives on" lifecycle is also reported in apple/container#2051 (https://github.com/apple/container/issues/2051), with a different symptom (two networks sharing a bridge, so tearing one down breaks the other's egress). It proposes the same mitigation: an anchor interface held with vmnet_interface_start_with_network.

Filed as:

  • FB24895271: reservations and rules discarded when the last interface is removed
  • FB24895264: the runtime forwarding calls fail on network-attached interfaces
  • FB24895282: suggestion for a network state-change callback and a DHCP lease query by MAC

Questions:

  1. Is losing reservations and rules when the network goes idle intended?
  2. Is holding an app-owned interface on the network (via vmnet_interface_start_with_network) so it never reaches zero interfaces a supported workaround, or does it risk other side effects?
Answered by DTS Engineer in 906957022

First up, thanks for all those bug reports FB24895271, FB24895264, FB24895282). Much appreciated!

Second, regarding your workaround, I asked around internally and it seems reasonable enough. We’re not aware of any specific negative consequences for having an interface instantiated but doing nothing.

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

First up, thanks for all those bug reports FB24895271, FB24895264, FB24895282). Much appreciated!

Second, regarding your workaround, I asked around internally and it seems reasonable enough. We’re not aware of any specific negative consequences for having an interface instantiated but doing nothing.

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

vmnet_network_ref loses its DHCP reservations and port-forwarding rules when its last interface leaves
 
 
Q