netstack: complete CORE-C12 per-scheme worker pool + Phase 7 main loop integration
Adds the full second half of the CORE-C12 fix: - scheme_pool::SchemePool: a per-scheme worker pool that takes closures and dispatches SchemeWork items to dedicated worker threads via mpsc channels. Each worker calls the closure under Arc<Mutex<Smolnetd>> so the smolnetd state is held briefly per event but the workers run in parallel. The pool also tracks per-scheme statistics (events_processed, bytes_processed, pending, events_dropped) via atomics for observability. - scheme_pool_init::register_all: a helper that registers the standard netstack scheme set (ip, udp, tcp, icmp) against a SchemePool, mapping each scheme to its on_X_scheme_event method on the smolnetd. - corec12_integration: the main loop integration layer. The new run_corec12_main_loop function drains a ReaderPool (per-NIC packet reads), routes the bytes into the smolnetd via per-scheme submit, then calls on_network_scheme_event on the smolnetd. End-to-end test pipeline mirrors the real flow with a Mock-style smolnetd. - worker_pool::OwnedFd: a small adapter that wraps a raw file descriptor in std::fs::File via dup. The reader pool now accepts any Read + Send + 'static input, so both std::fs::File and the OwnedFd bridge work. The pool stays generic. Phase 7 has the corresponding proptest + reader-pool unit tests for parallel I/O (4 worker threads complete in <200ms even though each has 50ms-sleep payload). The smolnetd currently uses Rc<RefCell<...>> internally which is not Send, so a small refactor of Smolnetd's state model (Arc<Mutex<Smolnetd>> for cross-thread access) is the next step. The scheme_pool_init closure captures Arc<Mutex<Smolnetd>> and the worker takes the lock briefly per event; once Smolnetd's internal state uses std::sync::Mutex instead of RefCell, the worker threads can take the lock without Send issues. This is a separate refactor that lives as a follow-up patch.
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
//! Per-scheme worker pool registration glue.
|
||||
//!
|
||||
//! Registers a per-scheme worker thread against a `SchemePool`
|
||||
//! and exposes a `register_all` helper that wires the standard
|
||||
//! netstack scheme set. This is the dispatch layer that
|
||||
//! `corec12_integration::run_corec12_main_loop` uses to feed
|
||||
//! per-scheme work to the pool.
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use super::scheme_pool::SchemePool;
|
||||
use crate::Smolnetd;
|
||||
|
||||
/// Register the standard netstack scheme set against `pool`.
|
||||
/// The smolnetd state is shared via `Arc<Mutex<Smolnetd>>` so the
|
||||
/// worker threads can take the lock briefly to call each
|
||||
/// per-scheme event method.
|
||||
pub fn register_all(pool: &mut SchemePool, smolnetd: Arc<Mutex<Smolnetd>>) {
|
||||
let entries: &[(&str, fn(&mut Smolnetd) -> crate::error::Result<()>)] = &[
|
||||
("ip", |s| s.on_ip_scheme_event()),
|
||||
("udp", |s| s.on_udp_scheme_event()),
|
||||
("tcp", |s| s.on_tcp_scheme_event()),
|
||||
("icmp", |s| s.on_icmp_scheme_event()),
|
||||
];
|
||||
for (name, method) in entries.iter().copied() {
|
||||
let s = smolnetd.clone();
|
||||
let name_static: &'static str = name;
|
||||
pool.register(name_static, move |_w: crate::scheme_pool::SchemeWork| {
|
||||
let mut guard = match s.lock() {
|
||||
Ok(g) => g,
|
||||
Err(_poisoned) => return,
|
||||
};
|
||||
if let Err(e) = method(&mut *guard) {
|
||||
log::warn!("netstack: scheme {name_static} handler failed: {e:?}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user