Skip to content

A wire that is down right now is a second nothing answered, not a host that could not ask - #469

Open
Japabu wants to merge 1 commit into
i219-deliveryfrom
wt/toyos-metalping-icmp
Open

Japabu wants to merge 1 commit into
i219-deliveryfrom
wt/toyos-metalping-icmp

Conversation

@Japabu

@Japabu Japabu commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Run 57 flashed the stick, set BootNext, rebooted the T14, and then ended at
exit 2 without reading the boot it had just staged:

toyos-metal: this host could not ask the one question this loop can put to a
boot that is still up: this host could not send an ICMP echo request to
192.168.1.46: No route to host (os error 65)
EXIT=2

The host was on the LAN either side of that window — a ping a minute before the
run answered in 11 ms and one two minutes after it in 4 ms. What lapsed was the
neighbour entry for the machine, which is what a reboot does to it: for the span
between reboot and the machine answering ssh again there is nothing on the
far end of the cable to resolve the address to, and the host kernel refuses the
send with EHOSTUNREACH rather than dropping the request on the floor.

That span is the only one Ping probes across, and a wire that is down inside
it is the state the probe exists to wait through — PING_SILENCE_SECS of quiet
is what a reply has to follow before it counts as this boot's. src/icmp.rs
read every failed send as this host's own failing, so the one second in which
the question could not be put ended the run. The boot itself completed; it was
read off the stick by hand afterwards.

What the classification now says

echo already answers three things: Ok(true) the address answered, Ok(false)
nothing answered inside the window, Err this host could not ask. The new case
goes inside that rather than beside it. A send refused with EHOSTUNREACH,
ENETUNREACH or ENETDOWN is Ok(false) — a silent second, exactly as a lost
reply is. Everything else is still Err and still reaches Refusal::Probe: a
permission the kernel withheld, a socket that is closed, a message it would not
take. wire_is_down names the three and nothing widens them, which is what
keeps Refusal::Probe meaning "this host could not ask" as against "nothing
answered".

The two checks

Negative control. wire_is_down's body reverted to false — the whole
change, onto the base the green arm was measured on — fails
a_wire_that_is_down_right_now_is_not_a_host_that_cannot_ask at errno 65, which
is the number run 57 printed. Widened the other way, to
e.raw_os_error().is_some(), it fails the same test at errno 1, EPERM. Both
directions were run; the real implementation is back and green.

Independent oracle: the recorded real failure. Run 57's own log, and the
platform's errno.h rather than this code — the test asserts that this host
spells EHOSTUNREACH 65, which is the number the loop printed when it refused
a boot that had in fact passed. The three names are the kernel's for a send
with nowhere to go; the test stages them through
io::Error::from_raw_os_error, opens no socket and reaches no address.

Gates

  • cargo test -p toyos-build --lib — 329 passed, 0 failed, 1 ignored, exit 0.
  • cargo run --bin toyos-metal -- --help — refused by the flag declaration
    before run, printing the accepted flags; it touches no machine.

The T14 was not run against: the orchestrator owns that machine.

🤖 Generated with Claude Code

https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK

…t that could not ask

Run 57 flashed the stick, set `BootNext`, rebooted the T14 and then ended at
exit 2 with

    this host could not ask the one question this loop can put to a boot that
    is still up: this host could not send an ICMP echo request to 192.168.1.46:
    No route to host (os error 65)

The host was on the LAN either side of it — a ping a minute before the run
answered in 11 ms and one two minutes after it in 4 ms. What lapsed was the
neighbour entry for the machine, which is what a reboot does to it: for the
span between `reboot` and the machine answering `ssh` again there is nothing
on the far end of the cable to resolve the address to, and the host kernel
refuses the send with `EHOSTUNREACH` rather than dropping the request.

That span is the only one `Ping` probes across. It is the come-back window,
and a wire that is down inside it is the state the probe exists to wait
through — `PING_SILENCE_SECS` of quiet is what a reply has to follow before
it counts as this boot's. `src/icmp.rs` read every failed send as this host's
own failing, so the one second the probe could not put the question ended the
run and the boot it had just staged went unmeasured. It had completed; it was
read off the stick by hand afterwards.

`echo` now answers `Ok(false)` — the silence it already answers for a reply
that never came — where the send was refused with `EHOSTUNREACH`, `ENETUNREACH`
or `ENETDOWN`, and `Err` for everything else. The three are named in
`wire_is_down` and nothing widens them: a permission the kernel withheld, a
socket that is closed and a message it would not take stay `Refusal::Probe`,
which is what keeps that refusal meaning "this host could not ask" as against
"nothing answered". The classification is the one already there — answered,
silent, refused — with the new case inside it rather than beside it.

`a_wire_that_is_down_right_now_is_not_a_host_that_cannot_ask` stages the real
errno values through `io::Error::from_raw_os_error` and asserts both arms,
including that this host spells `EHOSTUNREACH` 65, which is the number run 57
printed. No socket is opened and no address is reached.

Verified: `cargo test -p toyos-build --lib` and `cargo run --bin toyos-metal --`
with an argument the declaration does not carry, which refuses before `run` and
touches no machine. The T14 was not run against.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK
@Japabu
Japabu marked this pull request as ready for review September 16, 2026 15:16
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