virtio-devices: net: Report correct used length on TX and ctrl

The virtio spec says the used-ring length is bytes the device wrote to
device writable descriptors. The net TX descriptors are device readable
only (the device wrote nothing back) so the length needs to be 0. On the
ctrl queue the number of bytes reported was wrongly the size of the
status descriptor not the number of bytes written (the descriptor is
permitted to be larger).

Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
Rob Bradford
2026-04-18 11:13:57 +01:00
parent 305451cce4
commit 2a089db269
2 changed files with 10 additions and 9 deletions

View File

@@ -174,12 +174,10 @@ impl CtrlQueue {
.map_err(|e| Error::GuestMemory(GuestMemoryError::IOError(e)))?,
)
.map_err(Error::GuestMemory)?;
// Per virtio spec 2.6.8, used_len is the number of bytes written
// to device-writable descriptors. Only the status byte is written.
let len = status_desc.len();
// Per the virtio spec the used length is bytes the device wrote
// to device-writable descriptors; here just the 1-byte ack.
queue
.add_used(desc_chain.memory(), desc_chain.head_index(), len)
.add_used(desc_chain.memory(), desc_chain.head_index(), 1)
.map_err(Error::QueueAddUsed)?;
if !queue

View File

@@ -97,7 +97,7 @@ impl TxVirtio {
next_desc = desc_chain.next();
}
let len = if iovecs.is_empty() {
let bytes_sent = if iovecs.is_empty() {
0
} else {
// SAFETY: FFI call with correct arguments
@@ -129,7 +129,7 @@ impl TxVirtio {
self.counter_bytes += Wrapping(result as u64 - vnet_hdr_len() as u64);
self.counter_frames += Wrapping(1);
result as u32
result as u64
};
// For the sake of simplicity (similar to the RX rate limiting), we always
@@ -137,11 +137,14 @@ impl TxVirtio {
// limit, and simply stop processing oncoming `avail_desc` if any.
if let Some(rate_limiter) = rate_limiter {
rate_limit_reached = !rate_limiter.consume(1, TokenType::Ops)
|| !rate_limiter.consume(len as u64, TokenType::Bytes);
|| !rate_limiter.consume(bytes_sent, TokenType::Bytes);
}
// TX descriptors are device-readable only; the device wrote
// nothing back to guest memory, so per the virtio spec the used
// length is 0.
queue
.add_used(desc_chain.memory(), desc_chain.head_index(), len)
.add_used(desc_chain.memory(), desc_chain.head_index(), 0)
.map_err(NetQueuePairError::QueueAddUsed)?;
if !queue