Skip to content

Commit 35b9fa7

Browse files
committed
feat: fix retransmission issues with MRG_RXBUF
Fix retransmission issues introduced by enabling MRG_RXBUF. Do this by tracking total capacity of the `RxBuffer` struct and only return an iov slice if it contains at least 64K bytes. Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent d9a884f commit 35b9fa7

File tree

2 files changed

+15
-3
lines changed

2 files changed

+15
-3
lines changed

src/vmm/src/devices/virtio/net/device.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,10 @@ impl Net {
650650

651651
fn read_tap(&mut self) -> std::io::Result<usize> {
652652
if self.has_feature(u64::from(VIRTIO_NET_F_MRG_RXBUF)) {
653-
self.tap.read_iovec(self.rx_buffer.all_chains_mut_slice())
653+
let Some(s) = self.rx_buffer.all_chains_mut_slice() else {
654+
return Err(std::io::Error::from_raw_os_error(EAGAIN));
655+
};
656+
self.tap.read_iovec(s)
654657
} else {
655658
self.tap.read_iovec(self.rx_buffer.one_chain_mut_slice())
656659
}

src/vmm/src/devices/virtio/net/rx_buffer.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ pub struct RxBuffer {
6161
pub iovecs: IovRingBuffer,
6262
// Ring buffer of meta data about descriptor chains stored in the `iov_ring`.
6363
pub chain_infos: RingBuffer<ChainInfo>,
64+
// Total capacity this buffer holds.
65+
pub total_capacity: u32,
6466
// Number of descriptor chains we have used to process packets.
6567
pub used_descriptors: u16,
6668
}
@@ -72,6 +74,7 @@ impl RxBuffer {
7274
iovecs: IovRingBuffer::new()?,
7375
chain_infos: RingBuffer::new_with_size(u32::from(FIRECRACKER_MAX_QUEUE_SIZE)),
7476
used_descriptors: 0,
77+
total_capacity: 0,
7578
})
7679
}
7780

@@ -93,8 +96,12 @@ impl RxBuffer {
9396

9497
/// Returns a slice of underlying iovec for the all chains
9598
/// in the buffer.
96-
pub fn all_chains_mut_slice(&mut self) -> &mut [iovec] {
97-
self.iovecs.as_mut_slice()
99+
pub fn all_chains_mut_slice(&mut self) -> Option<&mut [iovec]> {
100+
if self.total_capacity < u32::from(u16::MAX) {
101+
None
102+
} else {
103+
Some(self.iovecs.as_mut_slice())
104+
}
98105
}
99106

100107
/// Add a new `DescriptorChain` that we received from the RX queue in the buffer.
@@ -151,6 +158,7 @@ impl RxBuffer {
151158
chain_len,
152159
chain_capacity,
153160
});
161+
self.total_capacity += chain_capacity;
154162

155163
Ok(())
156164
}
@@ -210,6 +218,7 @@ impl RxBuffer {
210218
.pop_front()
211219
.expect("This should never happen if write to the buffer succeded.");
212220
self.iovecs.pop_front(usize::from(iov_info.chain_len));
221+
self.total_capacity -= iov_info.chain_capacity;
213222

214223
if bytes_written <= iov_info.chain_capacity {
215224
write_used(iov_info.head_index, bytes_written, rx_queue);

0 commit comments

Comments
 (0)