Skip to content

Commit 88ee2bb

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 76b6316 commit 88ee2bb

File tree

3 files changed

+93
-19
lines changed

3 files changed

+93
-19
lines changed

src/devices/src/virtio/vsock/device.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ where
131131
let mem = match self.device_state {
132132
DeviceState::Activated(ref mem) => mem,
133133
// This should never happen, it's been already validated in the event handler.
134-
DeviceState::Inactive => return false,
134+
DeviceState::Inactive => unreachable!(),
135135
};
136136

137137
let mut have_used = false;
@@ -169,7 +169,7 @@ where
169169
let mem = match self.device_state {
170170
DeviceState::Activated(ref mem) => mem,
171171
// This should never happen, it's been already validated in the event handler.
172-
DeviceState::Inactive => return false,
172+
DeviceState::Inactive => unreachable!(),
173173
};
174174

175175
let mut have_used = false;

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

Lines changed: 90 additions & 16 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::VirtioDevice;
3233

3334
impl<B> Vsock<B>
3435
where
@@ -191,23 +192,28 @@ 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+
if self.is_activated() {
196+
let mut raise_irq = false;
197+
match source {
198+
_ if source == rxq => raise_irq = self.handle_rxq_event(event),
199+
_ if source == txq => raise_irq = self.handle_txq_event(event),
200+
_ if source == evq => raise_irq = self.handle_evq_event(event),
201+
_ if source == backend => {
202+
raise_irq = self.notify_backend(event);
203+
}
204+
_ if source == activate_evt => {
205+
self.handle_activate_event(event_manager);
206+
}
207+
_ => warn!("Unexpected vsock event received: {:?}", source),
202208
}
203-
_ if source == activate_evt => {
204-
self.handle_activate_event(event_manager);
209+
if raise_irq {
210+
self.signal_used_queue().unwrap_or_default();
205211
}
206-
_ => warn!("Unexpected vsock event received: {:?}", source),
207-
}
208-
209-
if raise_irq {
210-
self.signal_used_queue().unwrap_or_default();
212+
} else {
213+
warn!(
214+
"Vsock: The device is not yet activated. Spurious event received: {:?}",
215+
source
216+
);
211217
}
212218
}
213219

@@ -222,11 +228,13 @@ where
222228
#[cfg(test)]
223229
mod tests {
224230
use std::sync::atomic::Ordering;
231+
use std::sync::{Arc, Mutex};
225232

226-
use super::super::tests::TestContext;
233+
use super::super::tests::{EventHandlerContext, TestContext};
227234
use super::super::*;
228235
use super::*;
229236

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

tests/integration_tests/build/test_coverage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import host_tools.cargo_build as host # pylint: disable=import-error
2121

22-
COVERAGE_TARGET_PCT = 82.60
22+
COVERAGE_TARGET_PCT = 82.72
2323
COVERAGE_MAX_DELTA = 0.05
2424

2525
CARGO_KCOV_REL_PATH = os.path.join(host.CARGO_BUILD_REL_PATH, 'kcov')

0 commit comments

Comments
 (0)