mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-08-20 15:01:16 +00:00
vm-virtio: net: Refactor to support code reuse
Split out functions that work just on the TAP device and queues. Whilst doing so also improve the error handling to return Results rather than drop errors. This change also addresses a bug where the TAP event suppression could ineffectual because it was being enabled immediately after it may have been disabled: resume_rx -> rx_single_frame -> unregister_listener -> resume_rx -> register_listener. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
22be88d3fb
commit
3151b5d82a
@ -93,7 +93,7 @@ impl NetEpollHandler {
|
|||||||
self.rx.process_desc_chain(&mem, next_desc, &mut queue)
|
self.rx.process_desc_chain(&mem, next_desc, &mut queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_rx(&mut self, queue: &mut Queue) -> result::Result<(), DeviceError> {
|
fn process_rx(&mut self, queue: &mut Queue) -> result::Result<bool, DeviceError> {
|
||||||
// Read as many frames as possible.
|
// Read as many frames as possible.
|
||||||
loop {
|
loop {
|
||||||
match self.read_tap() {
|
match self.read_tap() {
|
||||||
@ -120,47 +120,13 @@ impl NetEpollHandler {
|
|||||||
}
|
}
|
||||||
if self.rx.deferred_irqs {
|
if self.rx.deferred_irqs {
|
||||||
self.rx.deferred_irqs = false;
|
self.rx.deferred_irqs = false;
|
||||||
self.signal_used_queue(queue)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resume_rx(&mut self, queue: &mut Queue) -> result::Result<(), DeviceError> {
|
fn resume_rx(&mut self, queue: &mut Queue) -> result::Result<bool, DeviceError> {
|
||||||
if self.rx.deferred_frame {
|
|
||||||
if self.rx_single_frame(queue) {
|
|
||||||
self.rx.deferred_frame = false;
|
|
||||||
// process_rx() was interrupted possibly before consuming all
|
|
||||||
// packets in the tap; try continuing now.
|
|
||||||
self.process_rx(queue)
|
|
||||||
} else if self.rx.deferred_irqs {
|
|
||||||
self.rx.deferred_irqs = false;
|
|
||||||
self.signal_used_queue(queue)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_tx(&mut self, mut queue: &mut Queue) -> result::Result<(), DeviceError> {
|
|
||||||
let mem = self.mem.memory();
|
|
||||||
|
|
||||||
self.tx.process_desc_chain(&mem, &mut self.tap, &mut queue);
|
|
||||||
self.signal_used_queue(queue)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_tap(&mut self) -> io::Result<usize> {
|
|
||||||
self.tap.read(&mut self.rx.frame_buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_rx_event(&mut self, mut queue: &mut Queue, queue_evt: &EventFd) {
|
|
||||||
if let Err(e) = queue_evt.read() {
|
|
||||||
error!("Failed to get rx queue event: {:?}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.resume_rx(&mut queue).unwrap();
|
|
||||||
if !self.rx_tap_listening {
|
if !self.rx_tap_listening {
|
||||||
register_listener(
|
register_listener(
|
||||||
self.epoll_fd,
|
self.epoll_fd,
|
||||||
@ -171,33 +137,91 @@ impl NetEpollHandler {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
self.rx_tap_listening = true;
|
self.rx_tap_listening = true;
|
||||||
}
|
}
|
||||||
|
if self.rx.deferred_frame {
|
||||||
|
if self.rx_single_frame(queue) {
|
||||||
|
self.rx.deferred_frame = false;
|
||||||
|
// process_rx() was interrupted possibly before consuming all
|
||||||
|
// packets in the tap; try continuing now.
|
||||||
|
self.process_rx(queue)
|
||||||
|
} else if self.rx.deferred_irqs {
|
||||||
|
self.rx.deferred_irqs = false;
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_tx_event(&mut self, mut queue: &mut Queue, queue_evt: &EventFd) {
|
fn process_tx(&mut self, mut queue: &mut Queue) -> result::Result<bool, DeviceError> {
|
||||||
if let Err(e) = queue_evt.read() {
|
let mem = self.mem.memory();
|
||||||
error!("Failed to get tx queue event: {:?}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.process_tx(&mut queue).unwrap();
|
self.tx.process_desc_chain(&mem, &mut self.tap, &mut queue);
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
fn process_rx_tap(&mut self, mut queue: &mut Queue) -> result::Result<bool, DeviceError> {
|
||||||
fn handle_rx_tap_event(&mut self, mut queue: &mut Queue) {
|
|
||||||
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
|
||||||
// until we manage to receive this deferred frame.
|
// until we manage to receive this deferred frame.
|
||||||
{
|
{
|
||||||
if self.rx_single_frame(&mut queue) {
|
if self.rx_single_frame(&mut queue) {
|
||||||
self.rx.deferred_frame = false;
|
self.rx.deferred_frame = false;
|
||||||
self.process_rx(&mut queue).unwrap();
|
self.process_rx(&mut queue)
|
||||||
} else if self.rx.deferred_irqs {
|
} else if self.rx.deferred_irqs {
|
||||||
self.rx.deferred_irqs = false;
|
self.rx.deferred_irqs = false;
|
||||||
self.signal_used_queue(&queue).unwrap();
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.process_rx(&mut queue).unwrap();
|
self.process_rx(&mut queue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_tap(&mut self) -> io::Result<usize> {
|
||||||
|
self.tap.read(&mut self.rx.frame_buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_rx_event(
|
||||||
|
&mut self,
|
||||||
|
mut queue: &mut Queue,
|
||||||
|
queue_evt: &EventFd,
|
||||||
|
) -> result::Result<(), DeviceError> {
|
||||||
|
if let Err(e) = queue_evt.read() {
|
||||||
|
error!("Failed to get rx queue event: {:?}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.resume_rx(&mut queue)? {
|
||||||
|
self.signal_used_queue(queue)?
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_tx_event(
|
||||||
|
&mut self,
|
||||||
|
mut queue: &mut Queue,
|
||||||
|
queue_evt: &EventFd,
|
||||||
|
) -> result::Result<(), DeviceError> {
|
||||||
|
if let Err(e) = queue_evt.read() {
|
||||||
|
error!("Failed to get tx queue event: {:?}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.process_tx(&mut queue)? {
|
||||||
|
self.signal_used_queue(queue)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_rx_tap_event(&mut self, queue: &mut Queue) -> result::Result<(), DeviceError> {
|
||||||
|
if self.process_rx_tap(queue)? {
|
||||||
|
self.signal_used_queue(queue)?
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
&mut self,
|
&mut self,
|
||||||
paused: Arc<AtomicBool>,
|
paused: Arc<AtomicBool>,
|
||||||
@ -277,13 +301,13 @@ impl NetEpollHandler {
|
|||||||
|
|
||||||
match ev_type {
|
match ev_type {
|
||||||
RX_QUEUE_EVENT => {
|
RX_QUEUE_EVENT => {
|
||||||
self.handle_rx_event(&mut queues[0], &queue_evts[0]);
|
self.handle_rx_event(&mut queues[0], &queue_evts[0])?;
|
||||||
}
|
}
|
||||||
TX_QUEUE_EVENT => {
|
TX_QUEUE_EVENT => {
|
||||||
self.handle_tx_event(&mut queues[1], &queue_evts[1]);
|
self.handle_tx_event(&mut queues[1], &queue_evts[1])?;
|
||||||
}
|
}
|
||||||
RX_TAP_EVENT => {
|
RX_TAP_EVENT => {
|
||||||
self.handle_rx_tap_event(&mut queues[0]);
|
self.handle_rx_tap_event(&mut queues[0])?;
|
||||||
}
|
}
|
||||||
KILL_EVENT => {
|
KILL_EVENT => {
|
||||||
debug!("KILL_EVENT received, stopping epoll loop");
|
debug!("KILL_EVENT received, stopping epoll loop");
|
||||||
|
Loading…
Reference in New Issue
Block a user