pub const METADATA_MAX_LEN: usize = MAX_OVERHEAD;
-pub const MAXQUEUE_ROUTE2WEB: usize = 15; // xxx: config
+
+// ----- Backpressure discussion -----
+
+// These two kinds of channels are sent blockingly, so this means the
+// task which calls route_packet can get this far ahead, before a
+// context switch to the receiving task is forced.
+pub const MAXQUEUE_ROUTE2USER: usize = 15;
+pub const MAXQUEUE_ROUTE2LOCAL: usize = 50;
+
+// This channel is sent with try_send, ie non-blocking. If the user
+// task becomes overloaded, requests will start to be rejected.
+pub const MAXQUEUE_WEBREQ2USER: usize = 5;
+
+// The user task prioritises 1. returning requests or discarding data,
+// 2. handling data routed to it. Ie it prefers to drain queues.
+//
+// The slocal task prioritises handling routed data and writing it
+// (synchronously) to the local kernel. So if the local kernel starts
+// blocking, all tasks may end up blocked waiting for things to drain.
+
#[derive(Debug)]
pub struct Global {
let (client_handles_send, client_handles_recv) = ics.iter()
.map(|_ic| {
let (web_send, web_recv) = mpsc::channel(
- 5 // xxx should me max_requests_outstanding but that's
- // marked client-only so needs rework
+ MAXQUEUE_WEBREQ2USER
);
let (route_send, route_recv) = mpsc::channel(
- MAXQUEUE_ROUTE2WEB
+ MAXQUEUE_ROUTE2USER
);
((web_send, route_send), (web_recv, route_recv))
}).unzip::<_,_,Vec<_>,Vec<_>>();
}).collect();
let (local_rx_send, local_tx_recv) = mpsc::channel(
- 50 // xxx configurable?
+ MAXQUEUE_ROUTE2LOCAL
);
let global = Arc::new(Global {