Skip to content

A radio leaves zone 0 with one station, whatever netdevs the last net zone left on it - #305

Merged
DevomB merged 5 commits into
mainfrom
radio-one-station
Oct 9, 2026
Merged

DevomB merged 5 commits into
mainfrom
radio-one-station

Conversation

@DevomB

@DevomB DevomB commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Builds on #304 (nic-renamed-plain); merge that first. This PR's own change is its last two commits, a0c093a and 0a2d261.

What was wrong. The net zone holds CAP_NET_ADMIN and generic netlink, so it can add netdevs to its radio (an AP, mesh or monitor one) or delete the one it has. When the zone ends, cfg80211 returns the wiphy to zone 0 with whatever netdevs are on it. Each case defeats the restart that is meant to give a fresh net zone:

  • A second netdev failed every later start. Both netdevs have device links, so both counted as physical. carry_nic of the first moved the wiphy, and the second went with it. carry_nic of the second then found no such interface, and the plumb failed. The zone crash-looped until a reboot.
  • A radio with no netdev was never carried. physical_interfaces lists netdevs, so Wi-Fi was gone until a reboot.

What changed.

  • compartments/kryptikd/src/netzone.rs: before physical_interfaces lists what to carry, a zone 0 radio with no netdev gets a station named nic<N> (bare_radios, read from sysfs). A radio with several netdevs has them all deleted and gets a fresh station too, since which one to keep would be the old zone's choice; the fresh station also takes the radio's own address. So each radio leaves with one station, as a boot gives it. linux-distro-fe suggested both: deleting the extras rather than letting them ride along (a second station can knock the first off its network, and an AP or monitor netdev the old zone made should not travel on), and deleting them all rather than keeping the first by name. A netdev that cannot be deleted goes along with its radio, which is still carried once. physical_interfaces_under now also returns each netdev's wiphy.
  • compartments/kryptikd/src/netlink.rs: new_station (NL80211_CMD_NEW_INTERFACE, iftype station, the name a %d template) and del_interface (NL80211_CMD_DEL_INTERFACE by ifindex).
  • compartments/kryptikd/src/netzone/tests.rs: bare_radios_are_the_ones_no_netdev_holds runs over a fake sysfs.
  • build/guest-tests/zones-check.sh: the new check radio-recarried runs after wifi-egress, over the simulated radio, in two rounds. First it adds a monitor netdev named amon0, which sorts before the station, inside the net zone. Then it deletes every netdev on the radio. Each round stops the service, waits for phy0 in zone 0, and starts the service again. The check passes only if the zone held 2 and then 0 netdevs on the radio, and the next zone got exactly one each time, a fresh nic<N>, and joined the access point again (READY with wifi=<the SSID>). wifi-beyond then runs on the re-carried radio.
  • tools/image/zones-test.sh: lists the verdict on a line of its own.
  • docs/design/net-zone.md: the wireless section and the tests.

How the run proves it. CI runs the unit test. In the Distro run's zones suite, radio-recarried fails on main: the first round's start fails at the second netdev and never comes READY with the SSID, and in the second round no radio is carried. With this change both rounds join.

Merges clean with every open PR except #180 and #207, which already conflict with main.

DevomB added 4 commits October 9, 2026 05:09
The net zone holds CAP_NET_ADMIN in its namespace and can give its NIC any
name the kernel takes: a leading dash, a quote, an escape, bytes that are
not UTF-8. When the zone ends the NIC comes back to zone 0 under that name,
and the next start handed it on as it was. A name that is not UTF-8 failed
every later start, since kryptikd looked up the lossy copy, and kept the
machine offline until a reboot. Any other reached the fresh zone's script:
a quote ended the name in the nft uplink set and could add kryptik0 to it,
and a leading dash reached dhcpcd as an option.

kryptikd now reads each physical interface's name as the kernel holds it,
with its index, and renames one that is not plain, a lower-case letter then
lower-case letters and digits, to the kernel's nic%d before it moves.
netzone-init.sh names the device to ip with dev, so a plain name that is
also an ip keyword is still read as a name.
… zone left on it

The net zone can add netdevs to its radio, an AP, mesh or monitor one, or
delete the one it has, and cfg80211 returns the wiphy to zone 0 with
whatever is on it. A second netdev failed every later start: the first
carry moved the wiphy with both, and the second found no such interface.
A radio with none was never carried again, so Wi-Fi was gone until a
reboot.

Before it lists what to carry, kryptikd now gives a radio with no netdev a
station named nic<N> (nl80211 NEW_INTERFACE), deletes all but the first
netdev of a radio with several (DEL_INTERFACE), and lists each radio once.
The zones suite leaves the net zone's radio with a monitor netdev beside
the station, then with none, restarts the zone each time, and sees the
next one get the radio with one station and join the access point again.
… since which to keep was the last zone's choice
@DevomB
DevomB merged commit f406578 into main Oct 9, 2026
21 checks passed
@DevomB
DevomB deleted the radio-one-station branch October 9, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant