vmm/devices/virtio/net/
event_handler.rs1use event_manager::{EventOps, Events, MutEventSubscriber};
5use vmm_sys_util::epoll::EventSet;
6
7use crate::devices::virtio::device::VirtioDevice;
8use crate::devices::virtio::net::device::Net;
9use crate::devices::virtio::net::{RX_INDEX, TX_INDEX};
10use crate::logger::{IncMetric, error, warn};
11
12impl Net {
13 const PROCESS_ACTIVATE: u32 = 0;
14 const PROCESS_VIRTQ_RX: u32 = 1;
15 const PROCESS_VIRTQ_TX: u32 = 2;
16 const PROCESS_TAP_RX: u32 = 3;
17 const PROCESS_RX_RATE_LIMITER: u32 = 4;
18 const PROCESS_TX_RATE_LIMITER: u32 = 5;
19
20 fn register_runtime_events(&self, ops: &mut EventOps) {
21 if let Err(err) = ops.add(Events::with_data(
22 &self.queue_evts[RX_INDEX],
23 Self::PROCESS_VIRTQ_RX,
24 EventSet::IN,
25 )) {
26 error!("Failed to register rx queue event: {}", err);
27 }
28 if let Err(err) = ops.add(Events::with_data(
29 &self.queue_evts[TX_INDEX],
30 Self::PROCESS_VIRTQ_TX,
31 EventSet::IN,
32 )) {
33 error!("Failed to register tx queue event: {}", err);
34 }
35 if let Err(err) = ops.add(Events::with_data(
36 &self.rx_rate_limiter,
37 Self::PROCESS_RX_RATE_LIMITER,
38 EventSet::IN,
39 )) {
40 error!("Failed to register rx queue event: {}", err);
41 }
42 if let Err(err) = ops.add(Events::with_data(
43 &self.tx_rate_limiter,
44 Self::PROCESS_TX_RATE_LIMITER,
45 EventSet::IN,
46 )) {
47 error!("Failed to register tx queue event: {}", err);
48 }
49 if let Err(err) = ops.add(Events::with_data(
50 &self.tap,
51 Self::PROCESS_TAP_RX,
52 EventSet::IN | EventSet::EDGE_TRIGGERED,
53 )) {
54 error!("Failed to register tap event: {}", err);
55 }
56 }
57
58 fn register_activate_event(&self, ops: &mut EventOps) {
59 if let Err(err) = ops.add(Events::with_data(
60 &self.activate_evt,
61 Self::PROCESS_ACTIVATE,
62 EventSet::IN,
63 )) {
64 error!("Failed to register activate event: {}", err);
65 }
66 }
67
68 fn process_activate_event(&self, ops: &mut EventOps) {
69 if let Err(err) = self.activate_evt.read() {
70 error!("Failed to consume net activate event: {:?}", err);
71 }
72 self.register_runtime_events(ops);
73 if let Err(err) = ops.remove(Events::with_data(
74 &self.activate_evt,
75 Self::PROCESS_ACTIVATE,
76 EventSet::IN,
77 )) {
78 error!("Failed to un-register activate event: {}", err);
79 }
80 }
81}
82
83impl MutEventSubscriber for Net {
84 fn process(&mut self, event: Events, ops: &mut EventOps) {
85 let source = event.data();
86 let event_set = event.event_set();
87
88 let supported_events = EventSet::IN;
91 if !supported_events.contains(event_set) {
92 warn!(
93 "Received unknown event: {:?} from source: {:?}",
94 event_set, source
95 );
96 return;
97 }
98
99 if self.is_activated() {
100 match source {
101 Self::PROCESS_ACTIVATE => self.process_activate_event(ops),
102 Self::PROCESS_VIRTQ_RX => self.process_rx_queue_event(),
103 Self::PROCESS_VIRTQ_TX => self.process_tx_queue_event(),
104 Self::PROCESS_TAP_RX => self.process_tap_rx_event(),
105 Self::PROCESS_RX_RATE_LIMITER => self.process_rx_rate_limiter_event(),
106 Self::PROCESS_TX_RATE_LIMITER => self.process_tx_rate_limiter_event(),
107 _ => {
108 warn!("Net: Spurious event received: {:?}", source);
109 self.metrics.event_fails.inc();
110 }
111 }
112 } else {
113 warn!(
114 "Net: The device is not yet activated. Spurious event received: {:?}",
115 source
116 );
117 }
118 }
119
120 fn init(&mut self, ops: &mut EventOps) {
121 if self.is_activated() {
126 self.register_runtime_events(ops);
127 } else {
128 self.register_activate_event(ops);
129 }
130 }
131}
132
133#[cfg(test)]
134pub mod tests {
135 use crate::devices::virtio::net::test_utils::NetQueue;
136 use crate::devices::virtio::net::test_utils::test::TestHelper;
137 use crate::devices::virtio::net::{MAX_BUFFER_SIZE, TX_INDEX};
138 use crate::test_utils::single_region_mem;
139
140 #[test]
141 fn test_event_handler() {
142 let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
143 let mut th = TestHelper::get_default(&mem);
144
145 th.add_desc_chain(NetQueue::Tx, 0, &[(0, 4096, 0)]);
147
148 let ev_count = th.event_manager.run_with_timeout(50).unwrap();
151 assert_eq!(ev_count, 0);
152
153 th.net().queue_evts[TX_INDEX].write(1).unwrap();
155 let ev_count = th.event_manager.run_with_timeout(50).unwrap();
156 assert_eq!(ev_count, 0);
157 assert_eq!(th.txq.used.idx.get(), 0);
159
160 th.activate_net();
162 th.event_manager
164 .run_with_timeout(50)
165 .expect("Metrics event timeout or error.");
166 assert_eq!(th.txq.used.idx.get(), 1);
168 }
169}