@@ -29,6 +29,7 @@ use utils::epoll::{EpollEvent, EventSet};
2929
3030use super :: device:: { Vsock , EVQ_INDEX , RXQ_INDEX , TXQ_INDEX } ;
3131use super :: VsockBackend ;
32+ use crate :: virtio:: VirtioDevice ;
3233
3334impl < B > Vsock < B >
3435where
@@ -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) ]
223229mod 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}
0 commit comments