Skip to content

Commit 8945700

Browse files
committed
devices: vsock: only handle events after device activation
Make sure all events are ignored prior to device activation. Added test for vsock event handling through EventManager. Signed-off-by: Adrian Catangiu <acatan@amazon.com>
1 parent 3b2d623 commit 8945700

File tree

1 file changed

+95
-18
lines changed

1 file changed

+95
-18
lines changed

src/devices/src/virtio/vsock/event_handler.rs

Lines changed: 95 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use utils::epoll::{EpollEvent, EventSet};
2929

3030
use super::device::{Vsock, EVQ_INDEX, RXQ_INDEX, TXQ_INDEX};
3131
use super::VsockBackend;
32+
use crate::virtio::DeviceState;
3233

3334
impl<B> Vsock<B>
3435
where
@@ -191,24 +192,32 @@ where
191192
let backend = self.backend.as_raw_fd();
192193
let activate_evt = self.activate_evt.as_raw_fd();
193194

194-
let mut raise_irq = false;
195-
196-
match source {
197-
_ if source == rxq => raise_irq = self.handle_rxq_event(event),
198-
_ if source == txq => raise_irq = self.handle_txq_event(event),
199-
_ if source == evq => raise_irq = self.handle_evq_event(event),
200-
_ if source == backend => {
201-
raise_irq = self.notify_backend(event);
195+
match self.device_state {
196+
DeviceState::Activated(_) => {
197+
let mut raise_irq = false;
198+
199+
match source {
200+
_ if source == rxq => raise_irq = self.handle_rxq_event(event),
201+
_ if source == txq => raise_irq = self.handle_txq_event(event),
202+
_ if source == evq => raise_irq = self.handle_evq_event(event),
203+
_ if source == backend => {
204+
raise_irq = self.notify_backend(event);
205+
}
206+
_ if source == activate_evt => {
207+
self.handle_activate_event(event_manager);
208+
}
209+
_ => warn!("Unexpected vsock event received: {:?}", source),
210+
}
211+
212+
if raise_irq {
213+
self.signal_used_queue().unwrap_or_default();
214+
}
202215
}
203-
_ if source == activate_evt => {
204-
self.handle_activate_event(event_manager);
205-
}
206-
_ => warn!("Unexpected vsock event received: {:?}", source),
207-
}
208-
209-
if raise_irq {
210-
self.signal_used_queue().unwrap_or_default();
211-
}
216+
DeviceState::Inactive => warn!(
217+
"Vsock: The device is not yet activated. Spurious event received: {:?}",
218+
source
219+
),
220+
};
212221
}
213222

214223
fn interest_list(&self) -> Vec<EpollEvent> {
@@ -222,11 +231,13 @@ where
222231
#[cfg(test)]
223232
mod tests {
224233
use std::sync::atomic::Ordering;
234+
use std::sync::{Arc, Mutex};
225235

226-
use super::super::tests::TestContext;
236+
use super::super::tests::{EventHandlerContext, TestContext};
227237
use super::super::*;
228238
use super::*;
229239

240+
use crate::virtio::device::VirtioDevice;
230241
use crate::virtio::vsock::packet::VSOCK_PKT_HDR_SIZE;
231242
use crate::virtio::VIRTIO_MMIO_INT_VRING;
232243
use crate::Error as DeviceError;
@@ -558,4 +569,70 @@ mod tests {
558569
GAP_SIZE as u32 + 100,
559570
);
560571
}
572+
573+
#[test]
574+
fn test_event_handler() {
575+
let mut event_manager = EventManager::new().unwrap();
576+
let test_ctx = TestContext::new();
577+
let EventHandlerContext {
578+
device,
579+
guest_rxvq,
580+
guest_txvq,
581+
..
582+
} = test_ctx.create_event_handler_context();
583+
584+
let vsock = Arc::new(Mutex::new(device));
585+
event_manager.add_subscriber(vsock.clone()).unwrap();
586+
587+
// Push a queue event
588+
// - the driver has something to send (there's data in the TX queue); and
589+
// - the backend has no pending RX data.
590+
{
591+
let mut device = vsock.lock().unwrap();
592+
device.backend.set_pending_rx(true);
593+
device.queue_events[TXQ_INDEX].write(1).unwrap();
594+
}
595+
596+
// EventManager should report no events since vsock has only registered
597+
// its activation event so far (even though there is also a queue event pending).
598+
let ev_count = event_manager.run_with_timeout(50).unwrap();
599+
assert_eq!(ev_count, 0);
600+
601+
// Manually force a queue event and check it's ignored pre-activation.
602+
{
603+
let mut device = vsock.lock().unwrap();
604+
605+
let raw_txq_evt = device.queue_events[TXQ_INDEX].as_raw_fd() as u64;
606+
// Artificially push event.
607+
device.process(
608+
&EpollEvent::new(EventSet::IN, raw_txq_evt),
609+
&mut event_manager,
610+
);
611+
612+
// Both available RX and TX descriptors should be untouched.
613+
assert_eq!(guest_rxvq.used.idx.get(), 0);
614+
assert_eq!(guest_txvq.used.idx.get(), 0);
615+
}
616+
617+
// Now activate the device.
618+
vsock
619+
.lock()
620+
.unwrap()
621+
.activate(test_ctx.mem.clone())
622+
.unwrap();
623+
// Process the activate event.
624+
let ev_count = event_manager.run_with_timeout(50).unwrap();
625+
assert_eq!(ev_count, 1);
626+
627+
// Handle the previously pushed queue event through EventManager.
628+
{
629+
let ev_count = event_manager
630+
.run_with_timeout(100)
631+
.expect("Metrics event timeout or error.");
632+
assert_eq!(ev_count, 1);
633+
// Both available RX and TX descriptors should have been used.
634+
assert_eq!(guest_rxvq.used.idx.get(), 1);
635+
assert_eq!(guest_txvq.used.idx.get(), 1);
636+
}
637+
}
561638
}

0 commit comments

Comments
 (0)