feat(minvmd): add net module with NetworkMode and gvproxy spawn - #463
Conversation
The 2024 edition makes `std::env::set_var`/`remove_var` unsafe. The new net module tests called them without an `unsafe` block, failing to compile (E0133) on the clippy, test, and build-macos CI jobs. Wrap each call in `unsafe` and serialise the env-mutating tests behind per-variable mutexes, matching the existing pattern in `image.rs`, so they don't race under parallel `cargo test`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds a shared ChangesShared gvproxy crate and minvmd network module
Sequence DiagramsequenceDiagram
participant Caller as minvmd Caller
participant NetModule as minvmd net.rs
participant GvproxyCrate as gvproxy crate
participant Gvproxy as gvproxy process
Caller->>NetModule: resolve_net_mode()
NetModule->>NetModule: read MINVMD_NETMODE
NetModule-->>Caller: NetworkMode::GvProxy
Caller->>NetModule: gvproxy_bin()
NetModule->>GvproxyCrate: gvproxy_bin("MINVMD_GVPROXY_PATH")
GvproxyCrate->>GvproxyCrate: read env override or default to "gvproxy"
GvproxyCrate-->>NetModule: PathBuf
NetModule-->>Caller: PathBuf
Caller->>NetModule: spawn_gvproxy(bin, net_fd)
NetModule->>GvproxyCrate: spawn_gvproxy(bin, net_fd)
GvproxyCrate->>Gvproxy: execute bin --fd {net_fd}
Gvproxy-->>GvproxyCrate: Child
GvproxyCrate-->>NetModule: anyhow::Result<Child>
NetModule-->>Caller: Child process
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/minimald/src/connection.rs`:
- Around line 149-154: The `.unwrap()` call on the `run_stream()` result in the
connection handler is converting handshake errors into panics that crash the
server. Instead of using `.unwrap()`, either propagate the error by returning a
Result type from the enclosing function and using the ? operator to let callers
handle handshake failures gracefully, or replace `.unwrap()` with `.expect()`
and include a descriptive error message explaining what happened if you
determine that panicking is intentional for this context. This allows the server
to recover from SSH handshake failures caused by malformed clients or network
issues rather than crashing the entire daemon.
In `@crates/minimald/src/server.rs`:
- Around line 206-208: Replace the direct await call to
`Connection::from_stream` with a match statement that handles both success and
error cases. On success, proceed with spawning the session handler task (the
current logic at lines 211-215). On error, log a warning message documenting the
handshake failure and continue to the next iteration of the accept loop,
ensuring that a single failed connection does not panic and crash the daemon.
In `@crates/minvmd/src/net.rs`:
- Around line 115-117: The code currently uses multiple separate static locks
(NETMODE_LOCK at line 115 and GVPROXY_PATH_LOCK at line 116, plus others
referenced in the "Also applies to" section) to synchronize environment variable
access in different tests. Since environment variable mutations are
process-global in Rust 2024, separate locks cannot prevent race conditions
between tests using different locks. Replace all these separate locks with a
single unified global lock and update all code locations where NETMODE_LOCK,
GVPROXY_PATH_LOCK, or any other separate lock is currently acquired to instead
acquire this single global lock before any set_var or remove_var operations.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1d093393-3e7f-45c4-bb28-88d9837e53b0
📒 Files selected for processing (6)
crates/minimald/src/connection.rscrates/minimald/src/guest.rscrates/minimald/src/server.rscrates/minimald/src/test_harness.rscrates/minvmd/src/lib.rscrates/minvmd/src/net.rs
💤 Files with no reviewable changes (1)
- crates/minimald/src/guest.rs
This branch had accidentally reverted recently-merged fixes that are unrelated to the net module: - `Connection::from_stream` was changed back to `.unwrap()` on the SSH handshake, so a malformed/dropped client would panic the accept loop. In the guest, minimald is pid-1, so the panic takes down the whole VM. - The accept loop in `server.rs` and the test harness lost their match-on-error handling that logs and continues. - `guest.rs` lost the pid-1 PATH setup needed for `git` lookups against the rootfs userland during interactive attach. Restore all four files to their origin/main state, keeping only the net module as this PR's contribution. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`set_var`/`remove_var` mutate process-global state, so the separate NETMODE_LOCK and GVPROXY_PATH_LOCK still let two tests touch the environment concurrently. Consolidate to one ENV_LOCK that serialises every env-mutating test in the module. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…crate twitchyliquid64 flagged on #463 that the net module should live where the Linux sandbox path can reuse it. Split the transport-agnostic gvproxy lookup/spawn into a new `gvproxy` leaf crate (deps: anyhow, tracing) consumed by minvmd. NetworkMode/resolve_net_mode stay in minvmd::net since TSI is a libkrun concept with no analogue elsewhere. spawn_gvproxy now takes the binary path as a parameter so each caller supplies its own override variable and FD source while reusing the same `gvproxy --fd` invocation: a socketpair end for libkrun's passt_fd on the macOS VM path, hakoniwa's rustslirp_tapfd on the Linux per-sandbox path. Revise the gvproxy networking spec + architecture to document the shared crate, the two per-path FD sources, and resolve the deferred-Linux open question (still out of scope here, but now unblocked). Refs: #453 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
docs/specs/03-spec-minvmd-networking-gvproxy/03-spec-minvmd-networking-gvproxy.md (1)
201-201: ⚡ Quick winStandardize British/American spelling for consistency.
Line 201 uses "serialise" (British spelling). Standardize to "serialize" (American spelling) to match the codebase's established convention.
✏️ Proposed fix
- single process-global `Mutex` (env mutation is `unsafe`/process-global on - the 2024 edition). Demonstrates the mode-selection logic is correct before + single process-global `Mutex` (env mutation is `unsafe`/process-global on + the 2024 edition). Demonstrates the mode-selection logic is correct beforeReplace "serialise" with "serialize" on line 201:
- tests serialise env-var mutation behind a + tests serialize env-var mutation behind a🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/specs/03-spec-minvmd-networking-gvproxy/03-spec-minvmd-networking-gvproxy.md` at line 201, The word "serialise" uses British spelling in the documentation text starting with "MINVMD_NETMODE=tsi is set; tests serialise env-var mutation behind a". Replace "serialise" with "serialize" to match the American spelling convention used throughout the codebase.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@docs/specs/03-spec-minvmd-networking-gvproxy/03-spec-minvmd-networking-gvproxy.md`:
- Line 201: The word "serialise" uses British spelling in the documentation text
starting with "MINVMD_NETMODE=tsi is set; tests serialise env-var mutation
behind a". Replace "serialise" with "serialize" to match the American spelling
convention used throughout the codebase.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: df37e628-7a1b-497d-9ecd-33a3b734b56d
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (7)
Cargo.tomlcrates/gvproxy/Cargo.tomlcrates/gvproxy/src/lib.rscrates/minvmd/Cargo.tomlcrates/minvmd/src/net.rsdocs/specs/03-spec-minvmd-networking-gvproxy/03-spec-minvmd-networking-gvproxy.mddocs/specs/03-spec-minvmd-networking-gvproxy/architecture.md
✅ Files skipped from review due to trivial changes (2)
- crates/gvproxy/Cargo.toml
- docs/specs/03-spec-minvmd-networking-gvproxy/architecture.md
[sdd-fastpath: tracking=453 tier=haiku]
Closes #453
Summary
Implements R1.1 and R1.2 from the minvmd networking gvproxy specification:
R1.1: Created
crates/minvmd/src/net.rswith:enum NetworkMode { GvProxy, Tsi }— the two supported transport modesfn resolve_net_mode() -> NetworkMode— readsMINVMD_NETMODEenv var; returnsGvProxyby default,Tsiwhen set to"tsi"fn gvproxy_bin() -> PathBuf— resolves gvproxy binary fromMINVMD_GVPROXY_PATHenv var or defaults to"gvproxy"(resolved via PATH)R1.2: Implemented:
fn spawn_gvproxy(net_fd: RawFd) -> Result<Child>— spawns gvproxy child with--fd <net_fd>argument, sets stdio to null, returns Child handleProof Artifacts
Test: unit tests for resolve_net_mode()
CLI: cargo check passes with no errors
CLI: cargo clippy passes
Changes
crates/minvmd/src/net.rs(new) — 158 linescrates/minvmd/src/lib.rs— 1 line addednetmoduleVerification
Merging this pull request closes task #453 and advances the tracking issue to
sdd:donefor final human review.Summary by CodeRabbit