refactor: extract networking ops behind traits, add mosnet OpenRPC backend, drop async_trait #61
No reviewers
Labels
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
geomind_code/my_hypervisor!61
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/networking-ops-traits"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This commit implements ADR-002 and ADR-003, restructuring the entire
networking layer to support pluggable backends — currently local shell
commands and mosnet's JSON-RPC 2.0 API over Unix socket.
== ADR-002: Drop async_trait crate ==
Replace the async_trait proc macro with explicit Pin<Box>
return types on all dyn-dispatched traits (NetworkBackend, StorageBackend).
The macro was hiding heap allocations and producing worse error messages.
On Rust 1.94, native async traits have been stable for 19 releases.
Audit finding: 7 of 8 trait method implementations do zero async work.
The entire networking layer is synchronous shell commands wrapped in
async sugar. Only VirtioFsStorage::prepare() genuinely awaits (a
tokio::time::sleep poll loop). The async signatures are retained because
the mosnet backend (ADR-003) performs real async I/O.
All trait methods now use unified lifetime 'a tying &self and &config
together, required because the boxed future captures both references.
== ADR-003: Extract networking operations behind traits ==
Three new async traits decompose networking into orthogonal concerns:
BridgeOps — bridge lifecycle (ensure_bridge, list_bridge_ports)
TapOps — TAP device lifecycle (create_tap, add_to_bridge, bring_up, delete_tap)
NatOps — port forwarding (add_port_forward, remove_port_forward)
IP allocation is deliberately excluded from TapOps. It is managed by
VmManager::allocate_bridge_ip() which tracks assigned IPs across VMs
via its own state store. mosnet has no visibility into these assignments.
Two backend implementations:
local/ — Current behavior preserved. Shell commands (ip, iptables)
moved from the old monolithic bridge.rs and tap.rs into
trait impls on LocalOps. Zero behavior change.
mosnet/ — JSON-RPC 2.0 client over /var/run/mosnet.sock. Calls
mosnet.bridge.add, mosnet.vm.create_tap (atomic: creates,
attaches, brings up in one call — add_to_bridge/bring_up
are no-ops), mosnet.vm.delete_tap, mosnet.nat.add_forward,
mosnet.nat.remove_forward. Self-contained protocol types
(~50 lines), no cross-project dependency.
TapNetwork is refactored from a unit struct to a composable struct
holding Arc, Arc, Arc.
Constructed via TapNetwork::local() or TapNetwork::new(bridge, tap, nat).
MyceliumNetwork now wraps a TapNetwork instance.
== Module structure ==
network/
traits.rs — NetworkBackend (high-level, unchanged API)
constants.rs — DEFAULT_BRIDGE_IP, SUBNET_PREFIX, GATEWAY, DEFAULT_BRIDGE
ops/mod.rs — BridgeOps, TapOps, NatOps traits + PortForwardRule
local/ — LocalOps implementing all three via shell commands
mosnet/ — MosnetOps implementing all three via JSON-RPC
client.rs — MosnetClient (tokio::sync::Mutex for Arc sharing)
protocol.rs — Request/Response/RpcError types
backends/
tap_backend.rs — TapNetwork (composable, holds dyn ops)
mycelium.rs — MyceliumNetwork (wraps TapNetwork)
namespace.rs — unchanged
== Files removed ==
network/bridge.rs — logic moved to local/bridge.rs + constants.rs
network/tap.rs — logic split into local/tap.rs, local/nat.rs, backends/tap_backend.rs
network/mycelium.rs — moved to backends/mycelium.rs
async-trait dep — removed from workspace and crate Cargo.toml
== Issues ==
== Verification ==
cargo check — clean
cargo clippy — clean
cargo test — 158 passed (1 pre-existing kernel test failure unrelated)
This commit implements ADR-002 and ADR-003, restructuring the entire networking layer to support pluggable backends — currently local shell commands and mosnet's JSON-RPC 2.0 API over Unix socket. == ADR-002: Drop async_trait crate == Replace the async_trait proc macro with explicit Pin<Box<dyn Future>> return types on all dyn-dispatched traits (NetworkBackend, StorageBackend). The macro was hiding heap allocations and producing worse error messages. On Rust 1.94, native async traits have been stable for 19 releases. Audit finding: 7 of 8 trait method implementations do zero async work. The entire networking layer is synchronous shell commands wrapped in async sugar. Only VirtioFsStorage::prepare() genuinely awaits (a tokio::time::sleep poll loop). The async signatures are retained because the mosnet backend (ADR-003) performs real async I/O. All trait methods now use unified lifetime 'a tying &self and &config together, required because the boxed future captures both references. == ADR-003: Extract networking operations behind traits == Three new async traits decompose networking into orthogonal concerns: BridgeOps — bridge lifecycle (ensure_bridge, list_bridge_ports) TapOps — TAP device lifecycle (create_tap, add_to_bridge, bring_up, delete_tap) NatOps — port forwarding (add_port_forward, remove_port_forward) IP allocation is deliberately excluded from TapOps. It is managed by VmManager::allocate_bridge_ip() which tracks assigned IPs across VMs via its own state store. mosnet has no visibility into these assignments. Two backend implementations: local/ — Current behavior preserved. Shell commands (ip, iptables) moved from the old monolithic bridge.rs and tap.rs into trait impls on LocalOps. Zero behavior change. mosnet/ — JSON-RPC 2.0 client over /var/run/mosnet.sock. Calls mosnet.bridge.add, mosnet.vm.create_tap (atomic: creates, attaches, brings up in one call — add_to_bridge/bring_up are no-ops), mosnet.vm.delete_tap, mosnet.nat.add_forward, mosnet.nat.remove_forward. Self-contained protocol types (~50 lines), no cross-project dependency. TapNetwork is refactored from a unit struct to a composable struct holding Arc<dyn BridgeOps>, Arc<dyn TapOps>, Arc<dyn NatOps>. Constructed via TapNetwork::local() or TapNetwork::new(bridge, tap, nat). MyceliumNetwork now wraps a TapNetwork instance. == Module structure == network/ traits.rs — NetworkBackend (high-level, unchanged API) constants.rs — DEFAULT_BRIDGE_IP, SUBNET_PREFIX, GATEWAY, DEFAULT_BRIDGE ops/mod.rs — BridgeOps, TapOps, NatOps traits + PortForwardRule local/ — LocalOps implementing all three via shell commands mosnet/ — MosnetOps implementing all three via JSON-RPC client.rs — MosnetClient (tokio::sync::Mutex for Arc sharing) protocol.rs — Request/Response/RpcError types backends/ tap_backend.rs — TapNetwork (composable, holds dyn ops) mycelium.rs — MyceliumNetwork (wraps TapNetwork) namespace.rs — unchanged == Files removed == network/bridge.rs — logic moved to local/bridge.rs + constants.rs network/tap.rs — logic split into local/tap.rs, local/nat.rs, backends/tap_backend.rs network/mycelium.rs — moved to backends/mycelium.rs async-trait dep — removed from workspace and crate Cargo.toml == Verification == cargo check — clean cargo clippy — clean cargo test — 158 passed (1 pre-existing kernel test failure unrelated)cc98a1c6c8138e06bffd138e06bffda13014c8d2a13014c8d233bbe4353c@ -0,0 +13,4 @@- **Hypervisor**: Cloud Hypervisor (external VMM process, controlled via REST API over Unix socket)- **Guest init**: Static musl binary (x86_64-unknown-linux-musl target)- **CLI framework**: clap (derive macros)- **Error handling**: thiserror (ChvmError enum)ChvmErrorisMyHyoervisorErrornow33bbe4353cdcbf7ab534