mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-22 04:25:21 +00:00
vm-virtio: net: Split network handling
Split handling of behaviour that is independent of the device itself so that it can be reused in the vhost-user-net device. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
237cb184b4
commit
2dbd11864e
@ -46,28 +46,16 @@ pub enum Error {
|
|||||||
|
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
struct NetEpollHandler {
|
struct NetQueuePair {
|
||||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
tap: Tap,
|
tap: Tap,
|
||||||
rx: RxVirtio,
|
rx: RxVirtio,
|
||||||
tx: TxVirtio,
|
tx: TxVirtio,
|
||||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
|
||||||
kill_evt: EventFd,
|
|
||||||
pause_evt: EventFd,
|
|
||||||
epoll_fd: RawFd,
|
epoll_fd: RawFd,
|
||||||
rx_tap_listening: bool,
|
rx_tap_listening: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetEpollHandler {
|
impl NetQueuePair {
|
||||||
fn signal_used_queue(&self, queue: &Queue) -> result::Result<(), DeviceError> {
|
|
||||||
self.interrupt_cb
|
|
||||||
.trigger(&VirtioInterruptType::Queue, Some(queue))
|
|
||||||
.map_err(|e| {
|
|
||||||
error!("Failed to signal used queue: {:?}", e);
|
|
||||||
DeviceError::FailedSignalingUsedQueue(e)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copies a single frame from `self.rx.frame_buf` into the guest. Returns true
|
// Copies a single frame from `self.rx.frame_buf` into the guest. Returns true
|
||||||
// if a buffer was used, and false if the frame must be deferred until a buffer
|
// if a buffer was used, and false if the frame must be deferred until a buffer
|
||||||
// is made available by the driver.
|
// is made available by the driver.
|
||||||
@ -160,6 +148,7 @@ impl NetEpollHandler {
|
|||||||
self.tx.process_desc_chain(&mem, &mut self.tap, &mut queue);
|
self.tx.process_desc_chain(&mem, &mut self.tap, &mut queue);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_rx_tap(&mut self, mut queue: &mut Queue) -> result::Result<bool, DeviceError> {
|
fn process_rx_tap(&mut self, mut queue: &mut Queue) -> result::Result<bool, DeviceError> {
|
||||||
if self.rx.deferred_frame
|
if self.rx.deferred_frame
|
||||||
// Process a deferred frame first if available. Don't read from tap again
|
// Process a deferred frame first if available. Don't read from tap again
|
||||||
@ -182,6 +171,24 @@ impl NetEpollHandler {
|
|||||||
fn read_tap(&mut self) -> io::Result<usize> {
|
fn read_tap(&mut self) -> io::Result<usize> {
|
||||||
self.tap.read(&mut self.rx.frame_buf)
|
self.tap.read(&mut self.rx.frame_buf)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NetEpollHandler {
|
||||||
|
net: NetQueuePair,
|
||||||
|
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||||
|
kill_evt: EventFd,
|
||||||
|
pause_evt: EventFd,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NetEpollHandler {
|
||||||
|
fn signal_used_queue(&self, queue: &Queue) -> result::Result<(), DeviceError> {
|
||||||
|
self.interrupt_cb
|
||||||
|
.trigger(&VirtioInterruptType::Queue, Some(queue))
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Failed to signal used queue: {:?}", e);
|
||||||
|
DeviceError::FailedSignalingUsedQueue(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_rx_event(
|
fn handle_rx_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -192,7 +199,7 @@ impl NetEpollHandler {
|
|||||||
error!("Failed to get rx queue event: {:?}", e);
|
error!("Failed to get rx queue event: {:?}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.resume_rx(&mut queue)? {
|
if self.net.resume_rx(&mut queue)? {
|
||||||
self.signal_used_queue(queue)?
|
self.signal_used_queue(queue)?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,15 +215,14 @@ impl NetEpollHandler {
|
|||||||
error!("Failed to get tx queue event: {:?}", e);
|
error!("Failed to get tx queue event: {:?}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.process_tx(&mut queue)? {
|
if self.net.process_tx(&mut queue)? {
|
||||||
self.signal_used_queue(queue)
|
self.signal_used_queue(queue)?
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_rx_tap_event(&mut self, queue: &mut Queue) -> result::Result<(), DeviceError> {
|
fn handle_rx_tap_event(&mut self, queue: &mut Queue) -> result::Result<(), DeviceError> {
|
||||||
if self.process_rx_tap(queue)? {
|
if self.net.process_rx_tap(queue)? {
|
||||||
self.signal_used_queue(queue)?
|
self.signal_used_queue(queue)?
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -229,9 +235,9 @@ impl NetEpollHandler {
|
|||||||
queue_evts: Vec<EventFd>,
|
queue_evts: Vec<EventFd>,
|
||||||
) -> result::Result<(), DeviceError> {
|
) -> result::Result<(), DeviceError> {
|
||||||
// Create the epoll file descriptor
|
// Create the epoll file descriptor
|
||||||
self.epoll_fd = epoll::create(true).map_err(DeviceError::EpollCreateFd)?;
|
self.net.epoll_fd = epoll::create(true).map_err(DeviceError::EpollCreateFd)?;
|
||||||
// Use 'File' to enforce closing on 'epoll_fd'
|
// Use 'File' to enforce closing on 'epoll_fd'
|
||||||
let epoll_file = unsafe { File::from_raw_fd(self.epoll_fd) };
|
let epoll_file = unsafe { File::from_raw_fd(self.net.epoll_fd) };
|
||||||
|
|
||||||
// Add events
|
// Add events
|
||||||
epoll::ctl(
|
epoll::ctl(
|
||||||
@ -265,15 +271,18 @@ impl NetEpollHandler {
|
|||||||
|
|
||||||
// If there are some already available descriptors on the RX queue,
|
// If there are some already available descriptors on the RX queue,
|
||||||
// then we can start the thread while listening onto the TAP.
|
// then we can start the thread while listening onto the TAP.
|
||||||
if queues[0].available_descriptors(&self.mem.memory()).unwrap() {
|
if queues[0]
|
||||||
|
.available_descriptors(&self.net.mem.memory())
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
epoll::ctl(
|
epoll::ctl(
|
||||||
epoll_file.as_raw_fd(),
|
epoll_file.as_raw_fd(),
|
||||||
epoll::ControlOptions::EPOLL_CTL_ADD,
|
epoll::ControlOptions::EPOLL_CTL_ADD,
|
||||||
self.tap.as_raw_fd(),
|
self.net.tap.as_raw_fd(),
|
||||||
epoll::Event::new(epoll::Events::EPOLLIN, u64::from(RX_TAP_EVENT)),
|
epoll::Event::new(epoll::Events::EPOLLIN, u64::from(RX_TAP_EVENT)),
|
||||||
)
|
)
|
||||||
.map_err(DeviceError::EpollCtl)?;
|
.map_err(DeviceError::EpollCtl)?;
|
||||||
self.rx_tap_listening = true;
|
self.net.rx_tap_listening = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); NET_EVENTS_COUNT];
|
let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); NET_EVENTS_COUNT];
|
||||||
@ -594,15 +603,17 @@ impl VirtioDevice for Net {
|
|||||||
queue_evt_pair.push(queue_evts.remove(0));
|
queue_evt_pair.push(queue_evts.remove(0));
|
||||||
|
|
||||||
let mut handler = NetEpollHandler {
|
let mut handler = NetEpollHandler {
|
||||||
mem: mem.clone(),
|
net: NetQueuePair {
|
||||||
tap: taps.remove(0),
|
mem: mem.clone(),
|
||||||
rx,
|
tap: taps.remove(0),
|
||||||
tx,
|
rx,
|
||||||
|
tx,
|
||||||
|
epoll_fd: 0,
|
||||||
|
rx_tap_listening,
|
||||||
|
},
|
||||||
interrupt_cb: interrupt_cb.clone(),
|
interrupt_cb: interrupt_cb.clone(),
|
||||||
kill_evt: kill_evt.try_clone().unwrap(),
|
kill_evt: kill_evt.try_clone().unwrap(),
|
||||||
pause_evt: pause_evt.try_clone().unwrap(),
|
pause_evt: pause_evt.try_clone().unwrap(),
|
||||||
epoll_fd: 0,
|
|
||||||
rx_tap_listening,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let paused = self.paused.clone();
|
let paused = self.paused.clone();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user