Skip to content

A NIC goes to the net zone with its own address, Wake-on-LAN off and an MTU of 1500 - #306

Merged
DevomB merged 10 commits into
mainfrom
nic-state-reset
Oct 9, 2026
Merged

DevomB merged 10 commits into
mainfrom
nic-state-reset

Conversation

@DevomB

@DevomB DevomB commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Builds on #305 (radio-one-station), which builds on #304; merge those first. This PR's own change is its last three commits, ab1e852, 9166a00 and dd0ce8b.

What was wrong. linux-distro-fe found that what the last net zone set on its NIC outlived it, until a reboot:

What changed.

  • compartments/kryptikd/src/netzone.rs: reset_nic runs in zone 0 before a NIC is carried, both for every NIC nic = "*" finds and for a NIC named in the zone file. It sets the address back to the one the hardware came with when they differ, sets the MTU of an Ethernet-type NIC to 1500 when it differs, removes any altnames, drops the alias, and turns Wake-on-LAN off when it is on. Each change and each failure is logged; a failure does not stop the start.
  • compartments/kryptikd/src/netlink.rs:
    • perm_mac_of uses ETHTOOL_GPERMADDR, which reads dev->perm_addr, the address register_netdevice keeps for a NIC whose driver gave one.
    • wol_off uses ETHTOOL_GWOL, then ETHTOOL_SWOL with wolopts 0. A driver with no Wake-on-LAN answers EOPNOTSUPP, which is not an error here.
    • set_link sends RTM_NEWLINK with IFLA_ADDRESS, IFLA_MTU and an empty IFLA_IFALIAS, by index.
    • names_left reads the altnames (IFLA_PROP_LIST, nested IFLA_ALT_IFNAME) and whether an alias is set, with one RTM_GETLINK; del_altnames removes the altnames with RTM_DELLINKPROP.
    • mac_of was test-only, which the release build refused at ab1e852; it is built always now.
    • transact_on sizes each read to its message (MSG_PEEK | MSG_TRUNC) under a 128 KiB cap instead of one 8 KiB buffer: a NIC may hold altnames until their list nears 64 KiB, and a listing that failed would have left kryptik0 in place (fe's read). del_altnames removes them 64 to a request, since a property list's length is 16 bits, and if the listing fails all the same, reset_nic still removes kryptik0 by name.
  • build/guest-tests/zones-check.sh: A NIC the net zone renamed is renamed nic<N> before the next net zone takes it #304's rename round now also gives the NIC the address 02:00:5e:00:53:01 and an MTU of 1400 inside the net zone, seventy altnames of a hundred bytes and then kryptik0, and an alias, before the rename. The new check uplink-state-reset sees the address and MTU come back to zone 0 under the hostile name, then requires the next net zone's nic<N> to read its own address (as recorded inside the zone first) and 1500, with no altname or alias left. On ab1e852 the altname alone keeps that start from coming READY.
  • tools/image/zones-test.sh: lists the verdict.
  • docs/design/net-zone.md: what is set back and why, and what is not.

What is not covered. EEE, offloads, rings and coalescing are not set back; they stay with the ethtool-netlink limit on the owner's list. Nor are a radio's wake triggers (nl80211 WoWLAN), which act only in suspend. The VM's virtio-net has no Wake-on-LAN, so no suite shows it being turned off; the check says so in an INFO line. Testing on physical hardware is planned for October 2026.

How the run proves it. CI compiles the new netlink calls and runs the unit suites. In the Distro run's zones suite, uplink-state-reset fails on #305's code: the next zone's nic0 keeps 02:00:5e:00:53:01 and MTU 1400. With this change it reads 52:54:00:12:34:56 and 1500.

DevomB added 10 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
…an MTU of 1500

What the last net zone set on its NIC outlived it: the address it chose,
which would follow the machine from network to network after the restart
meant to evict that zone; Wake-on-LAN, which lets anyone on the network
wake the machine; and the MTU. Before a NIC is carried, kryptikd now sets
its address back to the one the hardware came with (ETHTOOL_GPERMADDR),
its MTU to 1500, and Wake-on-LAN off (ETHTOOL_SWOL), for the NICs "*"
finds and for a NIC named in the zone file.

The zones suite's rename round also gives the NIC another address and an
MTU of 1400 inside the net zone, sees both come back to zone 0, and sees
the next net zone get the NIC with its own address and 1500.
An altname sits in the same name table as names and moves with the NIC,
so a net zone that gave its NIC the altname kryptik0 stopped every later
start making the bridge, as #304's plain names otherwise prevent. The
alias is free text that ip link prints. reset_nic now reads both with
RTM_GETLINK, removes the altnames with RTM_DELLINKPROP and drops the
alias with the address and MTU.

mac_of was test-only, which the release build refused.
…e reset

transact_on read into one 8 KiB buffer and refused a longer reply, and a
NIC may hold altnames until their list nears 64 KiB. A net zone that gave
its NIC seventy long altnames beside kryptik0 made the listing fail, so
kryptik0 stayed and the next start could not make the bridge. Each read is
now sized to its message (MSG_PEEK | MSG_TRUNC) under a 128 KiB cap,
del_altnames removes them 64 to a request, as the list's length is 16
bits, and a listing that fails all the same still removes kryptik0 by name.
@DevomB
DevomB marked this pull request as ready for review October 9, 2026 15:30
@DevomB
DevomB merged commit be2bf10 into main Oct 9, 2026
21 checks passed
@DevomB
DevomB deleted the nic-state-reset 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