Expand description
cbindgen:ignore Packed Virtqueue Implementation
This module provides a high-level API for virtio packed virtqueues, built on top of the lower-level ring primitives. It implements the VIRTIO 1.1+ packed ring format with proper memory ordering and event suppression support.
§Architecture
The implementation is split into layers:
-
High-level API ([
VirtqProducer], [VirtqConsumer]): Manages buffer allocation, chain lifecycle, and notification decisions. This is the recommended API for most use cases. -
Ring primitives ([
RingProducer], [RingConsumer]): Low-level descriptor ring operations with explicit buffer chain management. Use this when you need full control over buffer layouts or custom allocation strategies. -
Descriptor and event types ([
Descriptor], [EventSuppression]): Raw virtio data structures for direct memory manipulation.
§Quick Start
§Single Readable/Writable Chain
// Producer (driver) side - build and submit a send chain
let mut chain = producer.chain()
.readable(64)
.writable(128)
.build()?;
chain.write_all(b"request data")?;
let token = producer.submit(chain)?;
// ... wait for notification ...
if let Some(used) = producer.poll()? {
match used {
UsedChain::Data(_, segments) => process(segments),
UsedChain::Ack(_) => {}
}
}
// Consumer (device) side - receive a chain and reply/ack it
if let Some((chain, reply)) = consumer.poll(max_recv_len)? {
let request = chain.to_bytes();
match reply {
ReplyChain::Writable(mut wc) => {
let response = handle(request);
wc.write_all(&response)?;
consumer.complete(wc)?;
}
ReplyChain::Ack(ack) => {
consumer.complete(ack)?;
}
}
}
// Multiple pending completions (no borrow on consumer)
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 {
consumer.complete(reply)?;
}§Multiple Chains
Each submit checks event suppression and notifies independently. Use
[VirtqProducer::batch] when a higher-level protocol wants to publish
multiple chains and kick the queue once.
let mut batch = producer.batch();
for data in entries {
let mut chain = batch.chain()
.readable(data.len())
.writable(64)
.build()?;
chain.write_all(data)?;
batch.submit(chain)?;
}
batch.finish()?;§Completion Batching with Event Suppression
To receive a single notification when multiple requests complete:
// Submit chains
for data in entries {
let mut chain = producer.chain()
.readable(data.len())
.writable(64)
.build()?;
chain.write_all(data)?;
producer.submit(chain)?;
}
// Tell device: "notify me only after completing past this cursor"
let cursor = producer.used_cursor();
producer.set_used_suppression(SuppressionKind::Descriptor(cursor))?;
// Wait for single notification, then drain all responses
producer.drain(|used| {
if let UsedChain::Data(token, data) = used {
handle_response(token, data);
}
})?;§Event Suppression
Both sides can control when they want to be notified using [SuppressionKind]:
- [
SuppressionKind::Enable]: Always notify (default, lowest latency) - [
SuppressionKind::Disable]: Never notify (polling mode, lowest overhead) - [
SuppressionKind::Descriptor]: Notify at specific ring position (batching)
See [VirtqProducer::set_used_suppression] and [VirtqConsumer::set_avail_suppression].
§Low-Level API
For advanced use cases, the ring module exposes lower-level primitives:
- [
RingProducer] / [RingConsumer]: Direct ring access with [BufferChain] submission - [
BufferChainBuilder]: Construct scatter-gather buffer lists - [
RingCursor]: Track ring positions for event suppression
Example using low-level API:
let chain = BufferChainBuilder::new()
.readable(header_addr, header_len)
.readable(data_addr, data_len)
.writable(response_addr, response_len)
.build()?;
let result = ring_producer.submit_available_with_notify(&chain)?;
if result.notify {
kick_device();
}Modules§
- msg
- Wire format header for all virtqueue messages.
Structs§
- AckChain
- An ack-only reply for chains with no writable buffers.
- Allocation
- Allocation result
- Buffer
Chain - A chain of buffers ready for submission to the virtqueue.
- Buffer
Chain Builder - A builder for buffer chains using type-state to enforce readable/writable order.
- Buffer
Element - A single buffer element in a scatter-gather list.
- Buffer
Owner - The owner of a mapped buffer, ensuring its lifetime.
- Buffer
Pool - Two tier buffer pool with small and large slabs.
- Chain
Builder - Builder for configuring a descriptor chain’s buffer layout.
- Desc
Flags - Descriptor flags as defined by VIRTIO specification.
- Desc
Table - A table of descriptors stored in shared memory.
- Descriptor
- Event
Flags - Event
Suppression - Event suppression structure for controlling notifications.
- Layout
- Layout of a packed virtqueue ring in shared memory.
- Owned
Alloc - Pool-owned allocation that is returned to the pool on drop.
- Queue
Stats - Statistics about the current virtqueue state.
- Readable
- Type-state: Can add readable buffers
- Recv
Chain - Payload received from the producer, safely copied out of shared memory.
- Recycle
Pool - A recycling buffer provider with fixed-size slots.
- Ring
Consumer - Consumer (device) side of a packed virtqueue.
- Ring
Cursor - Tracks position in a ring buffer with wrap-around handling.
- Ring
Producer - Producer (driver) side of a packed virtqueue.
- Segments
- Ordered byte segments that make up one virtqueue payload.
- Segments
Buf - Borrowed
Bufcursor overSegments. - Send
Chain - A configured send chain ready for writing and submission.
- Submit
Batch - A scoped batch of producer submissions.
- Submit
Result - Result of submitting a buffer to the ring.
- Token
- A token representing a sent chain in the virtqueue.
- Used
Buffer - A buffer returned from the ring after being used by the device.
- Virtq
Consumer - A high-level virtqueue consumer (device side).
- Virtq
Producer - A high-level virtqueue producer (driver side).
- Writable
- Type-state: Can add writable buffers (no more readables allowed)
- Writable
Chain - A reply chain with writable buffer capacity.
Enums§
- Alloc
Error - MemOp
- Memory operation that failed in the backend.
- Reply
Chain - Consumer-side chain reply, either writable or ack-only.
- Ring
Error - Suppression
Kind - Event suppression mode for controlling when notifications are sent.
- Used
Chain - A used chain observed by the driver (producer) side.
- Virtq
Error - Errors that can occur in the virtqueue operations.
Traits§
- Buffer
Provider - Trait for buffer providers.
- MemOps
- Backend-provided memory access for virtqueue.
- Notifier
- A trait for notifying the consumer about virtqueue events.