Skip to content

The cable: netd takes its address from the network, and the T14 answers a ping on it - #442

Draft
Japabu wants to merge 15 commits into
mainfrom
lan-metal
Draft

The cable: netd takes its address from the network, and the T14 answers a ping on it#442
Japabu wants to merge 15 commits into
mainfrom
lan-metal

Conversation

@Japabu

@Japabu Japabu commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Stage 2's laptop half. The claim has been refused on every boot of it so far, so nothing here has a true positive yet — see What the machine has answered below.

netd takes this machine's address from the network. The interface carried 10.0.2.15/24 and a route to 10.0.2.2 as literals — one network's answer, and not the bench's. netd runs smoltcp's DHCPv4 client, asks under the host name toyos-t14, and writes the address, the default route and the resolvers together on a lease and their absence when one is lost. netd: ready is said on the first pass that settles the address question — a lease, or twenty seconds with none — because every arm in this suite that waits for that line connects right after it.

tests/lancase is the boot that runs netd in front of the T14's onboard I219 (8086:15fc at 00:1f.6), with one job that holds the machine up for twenty seconds. Only that arm names a PCI function (Arm::nictoyos-metal --nic), so only that arm reads the wire before the flash and pings across the window between the machine's two operating systems.

What identifies a reply, and what does not

How far into the window a reply came identifies nothing: the window holds the operating system that is leaving, this boot, and the one coming back. The T14 measured that — run 31 answered 57 s into the window on a boot whose claim was refused and whose netd never held the card, two seconds before its own sshd returned.

What identifies it is bootlog::host_second_inside_this_boot: the reply's wall clock must fall inside the span this boot's own records bracket, ending at Rebooting., and at or after the lease record. logd writes a wall clock on every record and the loop writes one beside the reply, and the two clocks' disagreement is bounded by the run's own data, not assumed: the loop records the host's clock at both ends of the down-window, and a boot whose records fall outside it is refused before anything is placed against them. boot.lancase.ping_secs stays priced as a cost and its ceiling_from says it is not a verdict.

What the machine has answered

Four boots, runs 28–31, all with the claim refused — first for want of MSI, then at the 32-bit BAR (issues/kernel/a-32-bit-bar-needs-the-host-bridges-aperture.md). So no boot has yet leased an address on that card, and no green reading exists for any lan. row. The three boot.lancase rows carry run 31's numbers, which are facts about the boot rather than about the claim: complete_ms 1258 (kernel.log:279), back_secs 59 and stick_secs 0 (boot.txt). ping_at was added by this branch, so no readback carries one and host_second_inside_this_boot has never run on real host-clock evidence.

The two checks

Negative control. The judge this branch replaces was a ceiling on ping_secs, and run 31 is the recorded real failure that reverting to it reproduces: that reply was inside the window and inside the ceiling and belonged to the next operating system. The judge that replaces it is shown refusing run 31's own records in a_second_past_the_reboot_record_is_the_next_operating_systems — the window opens no later than the boot's first record, so a reply 57 s in came at least 34 s after Rebooting. For the T14 arm itself, target/metal-lancontrol is this branch with pci:8086:15fcpci:8086:10d3, a card the machine does not have; run 30 is that arm, and its window was dark.

Oracles, none of them this tree's. QEMU's user-mode DHCP server, an RFC 2131 implementation nobody here wrote, checked field by field by lan_dhcp_lease. QEMU's own filter-dump of the wire, which is where the host-name option is read as bytes — no server logs it, so the frames are the only evidence the client asked at all. The development host's ping, an ICMP implementation nobody here wrote, pending the machine. And smoltcp's own limits, held at compile time: DNS_MAX_SERVER_COUNT >= DHCP_MAX_DNS_SERVER_COUNT, so netd's lease record can no longer name a resolver the stack dropped.

What is claimed and not measured

  • lan::on_metal requires the boot's lease address to equal the address Ubuntu held on the same function. That assumes the bench's router repeats a lease across the two operating systems — netd sends smoltcp's client identifier (option 61) and Ubuntu's client need not. Nothing has measured it. The refusal says so rather than concluding; what actually ties a reply to the boot is the MAC record and the wall-clock bracket, neither of which depends on it.
  • toyos-t14 resolves to nothing on the bench LAN (measured: the T14's DHCP resolvers are the ISP's). The option is sent and read off the wire; that it is recorded by any server is not claimed.

Dependencies

ping is a new host binary, outside CLAUDE.md's Rust-and-QEMU bar, declared in src/sourcegate.rs's HOST_SPAWNS beside ssh with its argument. It is reached only by src/metal.rs, only on the arm that names a NIC, and only across the window in which the T14 is running neither of its operating systems. No new crate, no new third-party file, no fetch. hubport and filter-dump are QEMU's own.

Gates

command exit result
cargo test --lib 0 303 passed, 0 failed, 1 ignored
cargo test --workspace --exclude toyos-build 0 138 suites ok, 0 failed
cargo run -- --clippy 0 5 invocations clean
cargo check -p netd (in userland/) 0 netd compiles, const assertion holds
qemu-system-x86_64 ... -netdev hubport ... -object filter-dump ... 0 on QEMU 11.1.0, the declared instrument: both accepted, and the pcap header is written
cargo test --test toyos-build -- lan_ not run: the shared sysroot is held by another worktree for an ABI change that is not on main, and this branch has no ABI diff to claim with. The guest arms — lan_dhcp_lease, lan_no_lease and the other network registrations — are unrun here and are CI's to render.

Draft: landing waits on the card being handed over on the machine.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz

Japabu and others added 15 commits September 8, 2026 15:07
The interface carried `10.0.2.15/24`, a default route to `10.0.2.2` and a
resolver at `10.0.2.3`, written into `main` as literals. That configuration was
one network's — QEMU's user-mode backend — and it was right about a machine
nobody had asked. The bench's router leases something else, so the T14 could
never have had an address at all.

netd now runs smoltcp's DHCPv4 client and applies what it is leased: the
address and its prefix, the default route, and the resolvers the DNS socket
queries, all three replaced together on a lease and dropped together when one
is lost. A route left standing over an address that is gone sends frames out
with a source nothing will answer, which is why they move as one.

Every DISCOVER and REQUEST carries the host-name option (RFC 2132 §3.14) with
`toyos-t14` in it: the bench's router is the only DHCP server in reach that
records a client's name, and what it records this machine under is what that
name then resolves to.

`netd: ready, at most N piped connections` moves from before the loop to the
first pass on which the address question is settled — a lease landed, or twenty
seconds passed with none. Sixteen arms in this suite wait for that line and then
connect; a netd that announced itself before it had an address would hand each
of them a stack with none. A machine that gets no lease says so in one line and
goes on serving, and its clients get their connects refused one at a time,
which is what they are already written to survive.

Measured against QEMU's user-mode DHCP server, which is an implementation of
RFC 2131 this repository did not write and whose lease is known field by field:
`lan_dhcp_lease` reads `10.0.2.15/24` from `10.0.2.2`, gateway `10.0.2.2`,
resolver `10.0.2.3`, eleven milliseconds after netd came up, and holds the
readiness line to arriving after it. The other fifteen network arms —
`netd_*`, `https_tls13`, `https_tls13_e1000e`, the five `log_stream` arms and
the four `sshd` ones — are green on the same tree.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
`tests/lancase` is the boot that runs netd in front of the ThinkPad's onboard
I219 at `00:1f.6`, `8086:15fc`. It is a directory of its own for the reason
`tests/e1000case` is: a program that names a card a machine does not have costs
an `init:` refusal line on every boot of the config that does, and no machine
has both. Nothing on it reaches the internal NVMe — there is no `[disks]` row,
and the PCI function netd claims is the only device any program on it names.

`lan_hold` is the one job on that boot and it asserts nothing: a metal boot is
about a second long, and nothing on a network can be asked of a machine that is
up for that long — the I219's link takes seconds to negotiate before a DHCP
discover can go out. It holds the machine up for twenty seconds and exits, and
its exit record is what says the machine stayed up for the whole window. It is
on `RUST_SKIP` because on any other boot it is twenty seconds of nothing.

The metal loop now pings the machine's own address across the window between
its two operating systems, and writes what it saw into the readback beside
`back_secs` and `stick_secs`. Three things make that a fact about the boot:

- The window opens when `ssh` stops answering and closes when it answers again,
  and inside it the only thing that can be running is the image this loop wrote.
- A reply counts only after the address has been silent for five seconds.
  `reboot` takes `sshd` down before the interface, so the machine that is
  already "down" by this loop's reckoning still answers ICMP for a moment, and a
  reply counted there is the operating system that is leaving.
- The address is resolved before the flash, through the same router's DNS that
  issues the lease, and the boot's own lease record is held to it afterwards:
  a run where the leased address and the pinged one differ is a ping something
  else answered.

`ping` is the host's own ICMP client, declared in `src/sourcegate.rs` beside
`ssh` and used nowhere else. It is an implementation of ICMP nobody here wrote,
which is what makes it an oracle for the stack under test rather than a second
opinion from it — and it is the only question this repository can ask a metal
boot while that boot is still running, everything else being on a stick read
minutes later.

The number is taken on every metal boot and claimed by one. Every other boot in
the suite runs no netd on that card, so its reading is Ubuntu answering on the
way back up — which is the separation `boot.lancase.ping_secs`'s ceiling will be
derived from. Until the machine has answered once, that row bounds the loop's
own wait and says so; the run that takes the first reading is the run that
tightens it, and every other row in the lancase block says the same.

`lan_dhcp_lease` is one name with two judges, as `metal_device_probe` is: under
QEMU it certifies netd's DHCP client against the user-mode backend's server,
and on the T14 it certifies the whole path — the kernel handing netd the I219's
function, the link, the lease from the bench's router under this machine's name,
and the host's ping answered at the leased address.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
`pcidev::bring_up` armed exactly one mechanism — `enable_msix(...).ok_or(Refusal::NoMsix)?` — so a
function that publishes no MSI-X capability was refused by name and its holder
never ran. Every function this project had handed to a process so far was a
virtio one and every one of those has MSI-X, so the refusal had only ever been
reached by `virtio_net_no_msix`'s deliberate `vectors=0`.

The ThinkPad T14's onboard NIC is not one of those. Measured on the machine,
not assumed: `/proc/interrupts` names its interrupt
`IR-PCI-MSI-0000:00:1f.6 ... enp0s31f6` and
`/sys/bus/pci/devices/0000:00:1f.6/msi_irqs/162` reads `mode=msi`, so Linux
drives that function on MSI. Flashed and booted (run 28), this kernel wrote
`pcidev: PCI 00:1f.6 NOT HANDED OVER — its MSI-X could not be armed`, netd
found no endowment and exited, and the bench's one cable stayed dark.

`bring_up` now arms MSI-X and falls back to MSI, and `Bound` holds whichever it
got. **The driver above the boundary cannot tell which one it is and does not
have to**: both deliver the same vector into the same `Interrupt`, and the claim
answers the same handle either way. What differs is where the message lives, and
therefore what a hand-over back has to write to silence it — `Armed::silence`
masks an MSI-X table entry or clears MSI Enable, and `Armed::undo` puts the
capability itself back off for a hand-over that armed a vector and was then
refused.

**MSI is not the weaker mechanism here, and the security argument is the same
one.** MSI-X's table is kept out of what the holder maps because a holder that
could rewrite it could point the device's message at any address the LAPIC
decodes. An MSI function's message is in its own config space, which `pcidev`
keeps: `config_read` is read-only and there is no writing counterpart. So MSI
needs no BAR withheld — the same rule reaching a different register file.

`Refusal::NoMsix` becomes `NoInterrupt` and says both mechanisms, because that
is now what it means. `PciDevice::disable_msi` is new and is `disable_msix`'s
counterpart: it sets the per-vector mask where the capability implements one and
clears MSI Enable, which every function has. `toyos_pci::msi` grows `disabled`
and the `MASKED`/`UNMASKED` mask values, host-tested — `disabled` deliberately
does not restore the Multiple Message Enable field an arming zeroed, or a
function would come back armed for as many vectors as it can raise.

The hand-over record now names the mechanism (`vector 0x28 on MSI-X`): it is the
first thing a machine that never heard from its device is asked, and it is not
something the driver above the boundary can see.

The two checks.

- **Negative control.** Run 28 on the T14 is this change reverted whole, on the
  base the granted claim will be measured against: the same `tests/lancase`
  image on this machine's own I219 with `bring_up` arming MSI-X alone. It
  refused the claim by name at 1.349 s, netd exited `code=0` at 2.268 s, and
  nothing answered on the cable for the twenty seconds the boot stayed up.
- **Independent oracles, two.** Linux's own reading of the same function, above
  — a driver nobody here wrote, saying that function is an MSI part. And the
  capability's register layout, which is the PCI spec's and which
  `toyos-pci/src/msi.rs`'s tests encode: the offsets of the address, data and
  mask registers all move with the 64-bit address bit, and writing a vector at
  the wrong one of them lands in whatever capability comes next in the list.
  Beside them, this kernel already produces the shape MSI must reproduce —
  `PCI 00:1f.3: msi address=0xfee00098 data=0x00000000` for the T14's HDA.

Green: `cargo test -p toyos-pci` (41), `cargo test --lib` (296),
`cargo run -- --clippy` (all five invocations), and the four guest arms that
read this module — `virtio_net_no_msix`, `iommu_virtio_platform`,
`pci_function_is_exclusive` and `userdev_dma_fault`. The MSI arm itself is
exercised on the T14 alone: no device QEMU models that a process may claim
publishes MSI without MSI-X, so there is no guest that can take that branch.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
…'s name

Run 28 on the T14 pinged `100.92.92.12` and got an answer 64 seconds into the
window, one second before `ssh` came back. That is the machine's Tailscale
address: `t14` resolves to it on this host, `Target::address` resolved the name,
and only the operating system that is leaving and the one coming back ever hold
it. The reply was Ubuntu's, and the five seconds of silence the loop waits for
did not catch it because Tailscale comes up late in Ubuntu's boot — a boot whose
netd never ran at all would have been reported the same way.

The name was the wrong question. What a boot of a metal image can answer on is
the address held on the PCI function that image *claims*, so that is what is
read: `Target::nic` names `0000:00:1f.6`, and `Driver::wire` asks the machine,
before the flash, which interface that function is, what MAC it has, and what
address `ip -4 -brief addr show` reports for it. Three reads, none of them a
root command and none of them a write. Measured just now over ssh: `enp0s31f6`,
`192.168.1.46/24`, gateway `192.168.1.1`, with the Mac on `192.168.1.47` — the
same LAN, which the Tailscale address is not.

The MAC is carried out beside the address and written into the readback, and
`lan::on_metal` holds the boot's own `netd: MAC` record to it. That is what
turns "something answered" into "this boot answered": a MAC does not change with
the operating system, so a driver reporting this one is the driver holding that
address, and a reply from any other interface at it is somebody else's. An
interface with no address at all is refused by name rather than read as the next
line's — `an_interface_with_no_address_is_refused_by_name` stages the T14's own
four-interface listing, Tailscale address included.

`Refusal::Unresolved` becomes `Refusal::Wire`, because the thing that can now
fail is the machine's account of one function rather than a name lookup.

Run 28's other numbers are recorded against their rows: `complete_ms` 1223,
`back_secs` 65, `stick_secs` 0. They are facts about a boot whose claim the
kernel refused, which makes them facts about the boot and not about the claim.
`ping_secs` gets none — no run has pinged the wire's address yet — and the
comment above the block says so rather than leaving a reader to assume the row
was simply not reached.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
The green arm cannot be measured until the kernel grants netd the I219's
function, and that is #443. Merged here so the image the T14 runs carries it;
when #443 lands, merging main into this branch is the same commits again.
… is reachable

Run 29 on the T14 armed the I219's MSI and then refused the hand-over:

    pcidev: 24 functions; a 32-bit window comes from 0x0..0x0, a 64-bit one from 0x603dc00000..0x6040c00000
    PCI 00:1f.6: msi address=0xfee000b8 data=0x00000000
    pcidev: PCI 00:1f.6 NOT HANDED OVER — this machine has no 2 MiB-aligned address space above what firmware assigned to put a BAR in

The refusal is correct and its wording was not. `window` places a BAR above
everything firmware described; in 64 bits that always exists, and below 4 GiB it
never does, because the platform's fixed MMIO is at `0xFEC00000` and the UEFI map
reaches it. So the message read as "this machine is full" where the truth is
"this module only ever looks above everything, and there is no above down there".
A 32-bit window is a free run *between* things.

Leaving the BAR where firmware put it is not the alternative: on this machine the
I219's `0xbcf00000` and the internal NVMe's `0xbce00000` are in one 2 MiB page,
and 2 MiB is the only page this kernel maps, so handing it over unmoved would put
a disk controller's registers inside netd's mapping.

What this change does is make the machine say what it has left, and name what is
missing.

`toyos_pci::bridge` decodes a Type 1 header's forwarded memory windows — bits
31:20 in the top twelve of each half, a limit that names the last megabyte, and
the base-above-limit encoding for a bridge that forwards nothing, which read
literally is a range that wraps. `PciDevice::forwarded_below_4g` reads them, and
the prefetchable one is dropped where its upper base puts it above 4 GiB.

`survey_low_space` runs on the machine where the low window comes out empty, and
only there: a boot with room says nothing, and thirty lines on every boot is a
log that has one channel off this bench. It merges the firmware map, this bus's
assigned BARs and every forwarded bridge window, prints the free runs of 2 MiB or
more, and ends with the sentence that matters —

    pcidev: a run above is a candidate and not a claim — what says whether an address below
    4 GiB reaches this bus at all is the host bridge's own aperture, which is ACPI's `_CRS`,
    and this kernel runs no AML

**Nothing here hands a run out**, and that is deliberate. An address outside the
host bridge's aperture is not free space, it is unrouted, and a read of it
answers ones — which `Refusal::Dead` cannot tell from a device that is not there.
Linux reads `_CRS` for exactly this and keeps its chipset registers as quirks for
firmware that gets `_CRS` wrong, not as an alternative to it. Guessing a range
here would be guessing whether a process's mapping reaches the bus or the void.
`issues/kernel/a-32-bit-bar-needs-the-host-bridges-aperture.md` carries the three
ways out and their prices.

`Refusal::NoWindow` was three facts under one name and is now three: `NoWindow
{ wide }` for a machine that published no window of that width — with the 32-bit
arm naming the aperture — `WindowFull { wide }` for one this module used up, and
`NoMappableBar` for a function with nothing to map, which is not about address
space at all and sent a reader to the allocator.

The two checks.

- **Negative control.** Run 29 is this change reverted whole, on this image and
  this machine: the same boot, the same claim, and a refusal that named no free
  run and no missing input. The next run on the T14 is the arm — the survey
  either prints runs or prints none, and either is a reading this repository does
  not have today.
- **Independent oracle.** The bridge window layout is the PCI-to-PCI Bridge
  Architecture Specification's, encoded in `toyos-pci/src/bridge.rs`'s tests: the
  address is bits 31:20 of each half and not the field's own offset, the limit
  names the last megabyte, and base-above-limit is "forwards nothing" rather than
  a wrapped range. Beside it, the T14's own enumeration is the check on the
  survey's arithmetic: `04:00.0` at `0xbce00000` and `00:1f.6` at `0xbcf00000`
  are behind bridges, so a survey that reported the page holding them free would
  be contradicted by the enumeration in the same log.

Green: `cargo test -p toyos-pci` 44, `cargo test --lib` 297,
`cargo run -- --clippy` all five invocations, and the four guest arms that read
`pcidev` — `virtio_net_no_msix`, `iommu_virtio_platform`,
`pci_function_is_exclusive`, `userdev_dma_fault`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
The green arm's claim stops at the 32-bit window, and the branch that says what
the machine has left below 4 GiB is stacked on #443. Merged here so the image
the T14 runs carries the survey; when both land, merging main is the same
commits again.
Run 29 armed the I219's MSI and stopped at the 32-bit BAR; run 30, the negative
control with the claim pointed at a card this machine does not have, did the
same boot with no netd at all. Both are recorded here.

`boot.lancase.complete_ms` 1257 and `back_secs` 61 are the machine's own numbers
off boots whose claim was refused — facts about the boot rather than about the
claim, so the readings stand. The two `lan.` rows still have none, because netd
never came up on either.

**Run 30 changed what `ping_secs` is for.** The control pinged 192.168.1.46 once
a second for its whole 61-second window and got nothing: this machine's wire
answers no earlier than its ssh, and the loop stops pinging when ssh answers. So
the number that row will hold is not "earlier than Ubuntu" — it is "at all",
because nothing answers at that address unless the boot brings it up. That is a
stronger control than the one the row was written for, and the `ceiling_from`
says so. It still waits on a green reading before it can be tightened to the
span a boot is actually up for.

The track file is brought up to what these three runs established: sshd's half
landed as #440, the I219 driver and DHCP are built and green under QEMU, and
what is left is the laptop — the claim, and the two things that wait on it. Its
constraints list carries three measurements instead of two guesses: the I219 is
an MSI part (`/proc/interrupts`, `msi_irqs/162`), `toyos-t14` resolves to
nothing on this LAN and `t14` resolves to a Tailscale address only Ubuntu holds,
and the 32-bit BAR shares its 2 MiB page with the internal NVMe — which is why
leaving it where firmware put it is not the way out either.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
Run 30's window was dark and I wrote a judge on that one sample: a reply
anywhere in the window is the boot's. Run 31 falsified it. That boot's claim was
refused at the 32-bit BAR, netd never held the card, and the loop still reported
`192.168.1.46 answered a ping 57 s into the window` — two seconds before the
machine's own `sshd` came back. The wire comes up before ssh does, and the loop
stops probing when ssh answers, so the reply was inside the window, inside the
ceiling, and belonged to the operating system after the boot. A ceiling on
`ping_secs` could never have told the two apart, whatever number it held.

What tells them apart is time against the boot's own timeline. `logd` writes a
wall clock on every record and the loop now writes one beside the reply; both
are UTC, the T14's clock being Ubuntu's from the network and this host's NTP's.
`bootlog::record_unix_secs` reads the one field in a log a host clock can be
held against, and `lan::the_boot_answered` is the judge:

- the reply is inside the span this boot's records bracket, ending at
  `Rebooting.` — anything after that is the next operating system, whatever its
  timing; and
- it is at or after the `netd: DHCP: lease` record, because a machine with no
  address answers nothing at that address.

Both halves are needed. The first alone would accept a reply from before netd
had an address; the second alone would accept run 31's, which came thirty-four
seconds after the boot had handed the machine back.

The bracket is about twenty-three seconds wide on this boot and the two clocks
agree to within a second, which is what makes comparing them admissible; a
machine whose clocks drifted further would show it as a reply just outside the
bracket rather than as a mystery, and the refusal prints both numbers.

`ping_secs` stays, priced, as the cost of a reply — it is a number worth
watching move and it is not a verdict, and its `ceiling_from` says so now rather
than claiming a separation it cannot make. `boot.txt` gains `ping_at`, written
only where something answered: a reply has a time or it did not happen.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
… name

The judge that says a host-side reply belongs to this boot lived in the
integration-test tree, where nothing could host-test it, beside a module that
declares itself the home for exactly its shape. It is now
`bootlog::host_second_inside_this_boot`: a log, the two ends of the host's own
window, the record the observation may not precede, and one second in; a verdict
out. Four tests cover both arms, and the fixture is three lines copied out of the
stick the T14 wrote rather than three runs' numbers blended together. The one
assertion that could not fail — `x + 57 > x + 23` over string constants — is
gone with it.

The clock skew the bracket rested on is measured instead of asserted. The loop
records the host's clock at both ends of the window in which the machine is
running neither of its operating systems, and the judge refuses a boot whose own
records do not lie inside it before it places anything against them. Nothing
claims the two clocks agree to within a second any more; the run's own data
bounds their disagreement.

The four cable fields in a readback are one `Cable`, and reading one refuses
every partial set by name. A file naming seconds and no wall clock used to fall
to a `_` arm and be reported as "nothing answered a ping" — the opposite of what
the run recorded, and the shape of every readback taken so far.

The reading and the probe belong to the boot that asks for them. `Arm::nic`
carries the PCI function into the driver's invocation as `--nic`, and only the
lancase arm sets it: `metal_device_probe`, `blackbox_unclaimed_page`, `ccorpus`
and every other registration no longer take three `ssh` reads and a ping thread
for a fact none of their judges reads. A host with no `ping` is now
`Refusal::Probe` rather than a dark cable, and `ping_secs` is judged once, by
`lan::on_metal`, instead of twice through a string compare that holed
`Unfit::Unpriced` for one field name.

`measured` on the lancase rows was run 29's boot time and the negative control's
`back_secs`. It is run 31's, the last boot of that config: 1258 ms and 59 s.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
…ame on a

wire that is read

`dns::Socket::update_servers` truncates to `DNS_MAX_SERVER_COUNT` and says
nothing, and smoltcp's default for it is one — so a lease offering three left
netd's own record naming two resolvers the stack did not have. The count is
raised in `userland/.cargo/config.toml` to the three a lease can carry
(`smoltcp::wire::DHCP_MAX_DNS_SERVER_COUNT`), and `dhcp.rs` holds the two
together with a `const` assertion: a build that lowers it again does not
compile. Nothing is dropped and nothing has to be reported as dropped.

`report_within` is deleted, and so is the `timeout.min` it fed. Its premise was
that a machine whose network never answers produces no timer, so the loop's own
delay is unbounded. `dhcpv4::Socket::poll_at` returns `PollAt::Time(retry_at)`
in every state, and netd's delay comes from `iface.poll_delay`, so a discovering
client already wakes the loop every ten seconds. The report now prints the
seconds it actually fired at instead of the constant it was written for.

The lease path and the lease-lost path are one writer. `Dhcp::write` takes the
lease or its absence and replaces the address, the default route and the
resolvers together, so the code that drops a lease is the code every boot
already runs.

Two things the lease boot cannot ask are now asked. `lan_no_lease` boots the
same config on an `e1000e` plugged into a hub with nothing else on it — the only
machine in this suite where a DHCP client gets no answer — and holds netd to
saying it has no address and then announcing itself anyway, which is what keeps
every arm waiting on that line from hanging. And `filter-dump` writes the frames
the client actually sent, so the host-name option is read as bytes on the wire:
a server that ignores it writes nothing about it, and there was no other place
the owner's hostname decision could be checked at all.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
Every prose finding in the review is answered by deletion rather than by a
rewrite. What went: what an earlier implementation bought, the alternatives that
were rejected, the borrow checker's opinion, a measurement with no command
behind it, the run numbers and the story of which run falsified which judge, the
comments that restate the line beneath them, and the fourteen-line header over
one `sleep`.

`tests/lancase/system.toml` claimed it changes "the pair of identifiers" against
`tests/e1000case`; it changes one. It also carried a boot parameter line no
config on this branch sets, copied in from its neighbour.

The track file had grown a stage table with a rationale per bullet, which is a
plan again. It is a paragraph, and what remains of the growth is two constraints
the bench measured: the I219 publishes MSI and no MSI-X, and its 32-bit BAR
shares a 2 MiB page with the internal NVMe.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
…mes it

`installing_the_rule_is_not_also_a_boot` enumerates every boot-describing flag
and asserts each one is refused beside `--install-sudoers`. `--nic` pushes onto
`about_a_boot` like the rest and was missing from that list.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
`Arm::nic`'s doc says why only the boot that names a function asks the cable,
and `invocation` said it again a screen later; `BootOptions::wire_dump`'s doc
says what the dump is for, and the argv said it again; and the partial-cable
test's own doc says which half would otherwise read as no answer, twice.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
…ne's name

`toyos-t14` resolves to nothing on the bench LAN. netd asks under the name and
the wire is read for the option; whether any server records it is not a claim
this repository can make, and the metal registration made it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGQ2H2aCwd1jfiNmjsiUvz
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