virtio-devices: net: Handle descriptor address translation

Since we're trying to move away from the translation happening in the
virtio-queue crate, the device itself is performing the address
translation when needed.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf
2022-01-26 17:12:15 +01:00
committed by Rob Bradford
parent ce984b73f5
commit 4becb11a44
5 changed files with 106 additions and 23 deletions

View File

@@ -10,8 +10,8 @@ use std::num::Wrapping;
use std::os::unix::io::{AsRawFd, RawFd};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use virtio_queue::Queue;
use vm_memory::{Bytes, GuestMemory, GuestMemoryAtomic};
use virtio_queue::{AccessPlatform, Queue};
use vm_memory::{Bytes, GuestAddress, GuestMemory, GuestMemoryAtomic};
#[derive(Clone)]
pub struct TxVirtio {
@@ -38,6 +38,7 @@ impl TxVirtio {
tap: &mut Tap,
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
rate_limiter: &mut Option<RateLimiter>,
access_platform: Option<&Arc<dyn AccessPlatform>>,
) -> Result<bool, NetQueuePairError> {
let mut retry_write = false;
let mut rate_limit_reached = false;
@@ -58,10 +59,20 @@ impl TxVirtio {
let mut iovecs = Vec::new();
while let Some(desc) = next_desc {
let desc_addr = if let Some(access_platform) = access_platform {
GuestAddress(
access_platform
.translate(desc.addr().0, u64::from(desc.len()))
.unwrap(),
)
} else {
desc.addr()
};
if !desc.is_write_only() && desc.len() > 0 {
let buf = desc_chain
.memory()
.get_slice(desc.addr(), desc.len() as usize)
.get_slice(desc_addr, desc.len() as usize)
.map_err(NetQueuePairError::GuestMemory)?
.as_ptr();
let iovec = libc::iovec {
@@ -72,7 +83,7 @@ impl TxVirtio {
} else {
error!(
"Invalid descriptor chain: address = 0x{:x} length = {} write_only = {}",
desc.addr().0,
desc_addr.0,
desc.len(),
desc.is_write_only()
);
@@ -161,6 +172,7 @@ impl RxVirtio {
tap: &mut Tap,
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
rate_limiter: &mut Option<RateLimiter>,
access_platform: Option<&Arc<dyn AccessPlatform>>,
) -> Result<bool, NetQueuePairError> {
let mut exhausted_descs = true;
let mut rate_limit_reached = false;
@@ -181,15 +193,36 @@ impl RxVirtio {
let desc = desc_chain
.next()
.ok_or(NetQueuePairError::DescriptorChainTooShort)?;
let num_buffers_addr = desc_chain.memory().checked_offset(desc.addr(), 10).unwrap();
let desc_addr = if let Some(access_platform) = access_platform {
GuestAddress(
access_platform
.translate(desc.addr().0, u64::from(desc.len()))
.unwrap(),
)
} else {
desc.addr()
};
let num_buffers_addr = desc_chain.memory().checked_offset(desc_addr, 10).unwrap();
let mut next_desc = Some(desc);
let mut iovecs = Vec::new();
while let Some(desc) = next_desc {
let desc_addr = if let Some(access_platform) = access_platform {
GuestAddress(
access_platform
.translate(desc.addr().0, u64::from(desc.len()))
.unwrap(),
)
} else {
desc.addr()
};
if desc.is_write_only() && desc.len() > 0 {
let buf = desc_chain
.memory()
.get_slice(desc.addr(), desc.len() as usize)
.get_slice(desc_addr, desc.len() as usize)
.map_err(NetQueuePairError::GuestMemory)?
.as_ptr();
let iovec = libc::iovec {
@@ -200,7 +233,7 @@ impl RxVirtio {
} else {
error!(
"Invalid descriptor chain: address = 0x{:x} length = {} write_only = {}",
desc.addr().0,
desc_addr.0,
desc.len(),
desc.is_write_only()
);
@@ -326,6 +359,7 @@ pub struct NetQueuePair {
pub rx_desc_avail: bool,
pub rx_rate_limiter: Option<RateLimiter>,
pub tx_rate_limiter: Option<RateLimiter>,
pub access_platform: Option<Arc<dyn AccessPlatform>>,
}
impl NetQueuePair {
@@ -333,9 +367,12 @@ impl NetQueuePair {
&mut self,
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
) -> Result<bool, NetQueuePairError> {
let tx_tap_retry =
self.tx
.process_desc_chain(&mut self.tap, queue, &mut self.tx_rate_limiter)?;
let tx_tap_retry = self.tx.process_desc_chain(
&mut self.tap,
queue,
&mut self.tx_rate_limiter,
self.access_platform.as_ref(),
)?;
// We got told to try again when writing to the tap. Wait for the TAP to be writable
if tx_tap_retry && !self.tx_tap_listening {
@@ -378,10 +415,12 @@ impl NetQueuePair {
&mut self,
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
) -> Result<bool, NetQueuePairError> {
self.rx_desc_avail =
!self
.rx
.process_desc_chain(&mut self.tap, queue, &mut self.rx_rate_limiter)?;
self.rx_desc_avail = !self.rx.process_desc_chain(
&mut self.tap,
queue,
&mut self.rx_rate_limiter,
self.access_platform.as_ref(),
)?;
let rate_limit_reached = self
.rx_rate_limiter
.as_ref()