pub struct VirtqConsumer<M, N> { /* private fields */ }Expand description
A high-level virtqueue consumer (device side).
The consumer receives chains from the producer (driver), processes them, and sends back replies. This is typically used on the device/host side.
§Example
let mut consumer = VirtqConsumer::new(layout, mem, notifier);
// Poll and process
while let Some((chain, reply)) = consumer.poll(MAX_RECV_LEN)? {
let data = chain.to_bytes();
match reply {
ReplyChain::Writable(mut wc) => {
let response = handle_request(data);
wc.write_all(&response)?;
consumer.complete(wc)?;
}
ReplyChain::Ack(ack) => {
consumer.complete(ack)?;
}
}
}
// Or defer completions
let mut pending = Vec::new();
while let Some((chain, reply)) = consumer.poll(MAX_RECV_LEN)? {
pending.push((process(chain), reply));
}
for (result, reply) in pending {
// ... complete later ...
consumer.complete(reply)?;
}Implementations§
Source§impl<M: MemOps + Clone, N: Notifier> VirtqConsumer<M, N>
impl<M: MemOps + Clone, N: Notifier> VirtqConsumer<M, N>
Sourcepub fn new(layout: Layout, mem: M, notifier: N) -> Self
pub fn new(layout: Layout, mem: M, notifier: N) -> Self
Create a new virtqueue consumer.
§Arguments
layout- Ring memory layoutmem- Memory ops implementation for reading/writing to shared memorynotifier- Callback for notifying the driver about replies
Sourcepub fn poll(
&mut self,
max_recv_len: usize,
) -> Result<Option<(RecvChain, ReplyChain<M>)>, VirtqError>
pub fn poll( &mut self, max_recv_len: usize, ) -> Result<Option<(RecvChain, ReplyChain<M>)>, VirtqError>
Poll for a single incoming chain from the driver.
Returns a RecvChain (copied data) and a ReplyChain (writable reply
capacity or ack token). Both are independent owned values with no borrow
on the consumer.
On VirtqError::BadChain, VirtqError::PayloadTooLarge, and
VirtqError::MemoryReadError the descriptor is returned to the driver
(completed with zero length) before the error is propagated, so a
rejected chain does not leak.
§Arguments
max_recv_len- Maximum receive payload size to copy. Payloads larger than this returnVirtqError::PayloadTooLarge.
§Errors
VirtqError::BadChain- Descriptor chain format not recognizedVirtqError::InvalidState- Descriptor ID collision (driver bug)VirtqError::MemoryReadError- Failed to read chain payload from shared memory
Sourcepub fn complete(
&mut self,
reply: impl Into<ReplyChain<M>>,
) -> Result<(), VirtqError>
pub fn complete( &mut self, reply: impl Into<ReplyChain<M>>, ) -> Result<(), VirtqError>
Submit a reply/ack for a received chain back to the ring.
Accepts both WritableChain (with written byte count) and
AckChain (zero-length) via the ReplyChain enum.
Clears the inflight slot and notifies the producer if event
suppression allows.
Sourcepub fn avail_cursor(&self) -> RingCursor
pub fn avail_cursor(&self) -> RingCursor
Get the current available cursor position.
Returns the position where the next available descriptor will be consumed. Useful for setting up descriptor-based event suppression.
Sourcepub fn used_cursor(&self) -> RingCursor
pub fn used_cursor(&self) -> RingCursor
Get the current used cursor position.
Returns the position where the next used descriptor will be written. Useful for setting up descriptor-based event suppression.
Sourcepub fn set_avail_suppression(
&mut self,
kind: SuppressionKind,
) -> Result<(), VirtqError>
pub fn set_avail_suppression( &mut self, kind: SuppressionKind, ) -> Result<(), VirtqError>
Configure event suppression for available buffer notifications.
This controls when the driver (producer) signals us about new buffers:
SuppressionKind::Enable- Always signal (default) - good for latencySuppressionKind::Disable- Never signal - caller must pollSuppressionKind::Descriptor- Signal only at specific cursor position
§Example: Polling Mode
consumer.set_avail_suppression(SuppressionKind::Disable)?;
loop {
while let Some((chain, reply)) = consumer.poll(1024)? {
process(chain, reply);
}
// ... do other work ...
}