Skip to content

Commit 2d3e45b

Browse files
committed
devices: net: activate through an activation event
Postpone net external events registration to device activation time. This makes the net device unaware of external events prior to its activation. During creation register a dedicated activation event which will notify the device when it's time to register the other external events sources. This activation event is unregistered after successful device activation. Code coverage slightly decreased because of untestable EventFd error cases. Signed-off-by: Adrian Catangiu <acatan@amazon.com>
1 parent 0fdf307 commit 2d3e45b

File tree

5 files changed

+269
-80
lines changed

5 files changed

+269
-80
lines changed

src/devices/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ pub enum Error {
4747
PayloadExpected,
4848
IoError(io::Error),
4949
NoAvailBuffers,
50+
SpuriousEvent,
5051
}

src/devices/src/virtio/net/device.rs

Lines changed: 89 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
use crate::virtio::net::Error;
99
use crate::virtio::net::Result;
1010
use crate::virtio::net::{MAX_BUFFER_SIZE, QUEUE_SIZE, QUEUE_SIZES, RX_INDEX, TX_INDEX};
11-
use crate::virtio::{ActivateResult, Queue, VirtioDevice, TYPE_NET, VIRTIO_MMIO_INT_VRING};
11+
use crate::virtio::{
12+
ActivateResult, DeviceState, Queue, VirtioDevice, TYPE_NET, VIRTIO_MMIO_INT_VRING,
13+
};
1214
use crate::{report_net_event_fail, Error as DeviceError};
1315
use dumbo::ns::MmdsNetworkStack;
1416
use dumbo::{EthernetFrame, MacAddr, MAC_ADDR_LEN};
@@ -59,8 +61,6 @@ pub struct Net {
5961
avail_features: u64,
6062
acked_features: u64,
6163

62-
mem: GuestMemoryMmap,
63-
6464
pub(crate) queues: Vec<Queue>,
6565
pub(crate) queue_evts: Vec<EventFd>,
6666

@@ -82,7 +82,8 @@ pub struct Net {
8282
config_space: Vec<u8>,
8383
guest_mac: Option<MacAddr>,
8484

85-
device_activated: bool,
85+
pub(crate) device_state: DeviceState,
86+
pub(crate) activate_evt: EventFd,
8687

8788
mmds_ns: Option<MmdsNetworkStack>,
8889

@@ -95,7 +96,6 @@ impl Net {
9596
pub fn new_with_tap(
9697
tap: Tap,
9798
guest_mac: Option<&MacAddr>,
98-
mem: GuestMemoryMmap,
9999
rx_rate_limiter: RateLimiter,
100100
tx_rate_limiter: RateLimiter,
101101
allow_mmds_requests: bool,
@@ -148,7 +148,6 @@ impl Net {
148148
tap,
149149
avail_features,
150150
acked_features: 0u64,
151-
mem,
152151
queues,
153152
queue_evts,
154153
rx_rate_limiter,
@@ -161,7 +160,8 @@ impl Net {
161160
tx_iovec: Vec::with_capacity(QUEUE_SIZE as usize),
162161
interrupt_status: Arc::new(AtomicUsize::new(0)),
163162
interrupt_evt: EventFd::new(libc::EFD_NONBLOCK).map_err(Error::EventFd)?,
164-
device_activated: false,
163+
device_state: DeviceState::Inactive,
164+
activate_evt: EventFd::new(libc::EFD_NONBLOCK).map_err(Error::EventFd)?,
165165
config_space,
166166
guest_mac,
167167
mmds_ns,
@@ -219,8 +219,13 @@ impl Net {
219219
// if a buffer was used, and false if the frame must be deferred until a buffer
220220
// is made available by the driver.
221221
fn rx_single_frame(&mut self) -> bool {
222+
let mem = match self.device_state {
223+
DeviceState::Activated(ref mem) => mem,
224+
// This should never happen, it's been already validated in the event handler.
225+
DeviceState::Inactive => return false,
226+
};
222227
let rx_queue = &mut self.queues[RX_INDEX];
223-
let mut next_desc = rx_queue.pop(&self.mem);
228+
let mut next_desc = rx_queue.pop(mem);
224229
if next_desc.is_none() {
225230
METRICS.net.no_rx_avail_buffer.inc();
226231
return false;
@@ -240,7 +245,7 @@ impl Net {
240245

241246
let limit = cmp::min(write_count + desc.len as usize, self.rx_bytes_read);
242247
let source_slice = &self.rx_frame_buf[write_count..limit];
243-
let write_result = self.mem.write_slice(source_slice, desc.addr);
248+
let write_result = mem.write_slice(source_slice, desc.addr);
244249

245250
match write_result {
246251
Ok(()) => {
@@ -270,7 +275,7 @@ impl Net {
270275
}
271276
}
272277

273-
rx_queue.add_used(&self.mem, head_index, write_count as u32);
278+
rx_queue.add_used(mem, head_index, write_count as u32);
274279

275280
// Mark that we have at least one pending packet and we need to interrupt the guest.
276281
self.rx_deferred_irqs = true;
@@ -406,6 +411,12 @@ impl Net {
406411
}
407412

408413
fn process_tx(&mut self) -> result::Result<(), DeviceError> {
414+
let mem = match self.device_state {
415+
DeviceState::Activated(ref mem) => mem,
416+
// This should never happen, it's been already validated in the event handler.
417+
DeviceState::Inactive => return Err(DeviceError::SpuriousEvent),
418+
};
419+
409420
// The MMDS network stack works like a state machine, based on synchronous calls, and
410421
// without being added to any event loop. If any frame is accepted by the MMDS, we also
411422
// trigger a process_rx() which checks if there are any new frames to be sent, starting
@@ -414,7 +425,7 @@ impl Net {
414425
let mut raise_irq = false;
415426
let tx_queue = &mut self.queues[TX_INDEX];
416427

417-
while let Some(head) = tx_queue.pop(&self.mem) {
428+
while let Some(head) = tx_queue.pop(mem) {
418429
// If limiter.consume() fails it means there is no more TokenType::Ops
419430
// budget and rate limiting is in effect.
420431
if !self.tx_rate_limiter.consume(1, TokenType::Ops) {
@@ -459,7 +470,7 @@ impl Net {
459470
for (desc_addr, desc_len) in self.tx_iovec.drain(..) {
460471
let limit = cmp::min((read_count + desc_len) as usize, self.tx_frame_buf.len());
461472

462-
let read_result = self.mem.read_slice(
473+
let read_result = mem.read_slice(
463474
&mut self.tx_frame_buf[read_count..limit as usize],
464475
desc_addr,
465476
);
@@ -491,7 +502,7 @@ impl Net {
491502
process_rx_for_mmds = true;
492503
}
493504

494-
tx_queue.add_used(&self.mem, head_index, 0);
505+
tx_queue.add_used(mem, head_index, 0);
495506
raise_irq = true;
496507
}
497508

@@ -542,8 +553,13 @@ impl Net {
542553
}
543554

544555
pub fn process_tap_rx_event(&mut self) {
556+
let mem = match self.device_state {
557+
DeviceState::Activated(ref mem) => mem,
558+
// This should never happen, it's been already validated in the event handler.
559+
DeviceState::Inactive => return,
560+
};
545561
METRICS.net.rx_tap_event_count.inc();
546-
if self.queues[RX_INDEX].is_empty(&self.mem) {
562+
if self.queues[RX_INDEX].is_empty(mem) {
547563
METRICS.net.no_rx_avail_buffer.inc();
548564
return;
549565
}
@@ -676,20 +692,28 @@ impl VirtioDevice for Net {
676692
}
677693

678694
fn is_activated(&self) -> bool {
679-
self.device_activated
695+
match self.device_state {
696+
DeviceState::Inactive => false,
697+
DeviceState::Activated(_) => true,
698+
}
680699
}
681700

682-
fn activate(&mut self, _: GuestMemoryMmap) -> ActivateResult {
683-
self.device_activated = true;
701+
fn activate(&mut self, mem: GuestMemoryMmap) -> ActivateResult {
702+
if self.activate_evt.write(1).is_err() {
703+
error!("Net: Cannot write to activate_evt");
704+
return Err(super::super::ActivateError::BadActivate);
705+
}
706+
self.device_state = DeviceState::Activated(mem);
684707
Ok(())
685708
}
686709
}
687710

688711
#[cfg(test)]
689-
mod tests {
712+
pub(crate) mod tests {
690713
use std::net::Ipv4Addr;
691714
use std::os::unix::io::AsRawFd;
692715
use std::sync::atomic::{AtomicUsize, Ordering};
716+
use std::sync::Mutex;
693717
use std::time::Duration;
694718
use std::{io, mem, thread};
695719

@@ -741,7 +765,7 @@ mod tests {
741765
}
742766
}
743767

744-
trait TestUtil {
768+
pub(crate) trait TestUtil {
745769
fn default_net(test_mutators: TestMutators) -> Net;
746770
fn default_guest_mac() -> MacAddr;
747771
fn default_guest_memory() -> GuestMemoryMmap;
@@ -762,7 +786,6 @@ mod tests {
762786
let mut net = Net::new_with_tap(
763787
tap,
764788
Some(&guest_mac),
765-
Net::default_guest_memory(),
766789
RateLimiter::default(),
767790
RateLimiter::default(),
768791
true,
@@ -812,7 +835,6 @@ mod tests {
812835
self.queues.clear();
813836
self.queues.push(rxq);
814837
self.queues.push(txq);
815-
self.activate(self.mem.clone()).unwrap();
816838
}
817839
}
818840

@@ -931,12 +953,13 @@ mod tests {
931953
}
932954

933955
#[test]
934-
fn test_event_handling() {
956+
fn test_event_processing() {
935957
let mut event_manager = EventManager::new().unwrap();
936958
let mut net = Net::default_net(TestMutators::default());
937-
let mem_clone = net.mem.clone();
938-
let (rxq, txq) = Net::virtqueues(&mem_clone);
959+
let mem = Net::default_guest_memory();
960+
let (rxq, txq) = Net::virtqueues(&mem);
939961
net.assign_queues(rxq.create_queue(), txq.create_queue());
962+
net.activate(mem.clone()).unwrap();
940963

941964
let daddr = 0x2000;
942965
assert!(daddr > txq.end().0);
@@ -1213,9 +1236,10 @@ mod tests {
12131236
fn test_process_error_cases() {
12141237
let mut event_manager = EventManager::new().unwrap();
12151238
let mut net = Net::default_net(TestMutators::default());
1216-
let mem_clone = net.mem.clone();
1217-
let (rxq, txq) = Net::virtqueues(&mem_clone);
1239+
let mem = Net::default_guest_memory();
1240+
let (rxq, txq) = Net::virtqueues(&mem);
12181241
net.assign_queues(rxq.create_queue(), txq.create_queue());
1242+
net.activate(mem.clone()).unwrap();
12191243

12201244
// RX rate limiter events should error since the limiter is not blocked.
12211245
// Validate that the event failed and failure was properly accounted for.
@@ -1242,15 +1266,27 @@ mod tests {
12421266
fn test_invalid_event() {
12431267
let mut event_manager = EventManager::new().unwrap();
12441268
let mut net = Net::default_net(TestMutators::default());
1245-
let mem_clone = net.mem.clone();
1246-
let (rxq, txq) = Net::virtqueues(&mem_clone);
1269+
1270+
let mem = Net::default_guest_memory();
1271+
let (rxq, txq) = Net::virtqueues(&mem);
12471272
net.assign_queues(rxq.create_queue(), txq.create_queue());
1273+
net.activate(mem.clone()).unwrap();
1274+
1275+
let net = Arc::new(Mutex::new(net));
1276+
event_manager.add_subscriber(net.clone()).unwrap();
1277+
1278+
// Process the activate event.
1279+
let ev_count = event_manager.run_with_timeout(50).unwrap();
1280+
assert_eq!(ev_count, 1);
12481281

1282+
// Inject invalid event.
12491283
let invalid_event = EpollEvent::new(EventSet::IN, 1000);
12501284
check_metric_after_block!(
12511285
&METRICS.net.event_fails,
12521286
1,
1253-
net.process(&invalid_event, &mut event_manager)
1287+
net.lock()
1288+
.unwrap()
1289+
.process(&invalid_event, &mut event_manager)
12541290
);
12551291
}
12561292

@@ -1265,9 +1301,10 @@ mod tests {
12651301
};
12661302

12671303
let mut net = Net::default_net(test_mutators);
1268-
let mem_clone = net.mem.clone();
1269-
let (rxq, txq) = Net::virtqueues(&mem_clone);
1304+
let mem = Net::default_guest_memory();
1305+
let (rxq, txq) = Net::virtqueues(&mem);
12701306
net.assign_queues(rxq.create_queue(), txq.create_queue());
1307+
net.activate(mem.clone()).unwrap();
12711308

12721309
// The RX queue is empty.
12731310
let tap_event = EpollEvent::new(EventSet::IN, net.tap.as_raw_fd() as u64);
@@ -1290,9 +1327,10 @@ mod tests {
12901327
fn test_rx_rate_limiter_handling() {
12911328
let mut event_manager = EventManager::new().unwrap();
12921329
let mut net = Net::default_net(TestMutators::default());
1293-
let mem_clone = net.mem.clone();
1294-
let (rxq, txq) = Net::virtqueues(&mem_clone);
1330+
let mem = Net::default_guest_memory();
1331+
let (rxq, txq) = Net::virtqueues(&mem);
12951332
net.assign_queues(rxq.create_queue(), txq.create_queue());
1333+
net.activate(mem.clone()).unwrap();
12961334

12971335
net.rx_rate_limiter = RateLimiter::new(0, None, 0, 0, None, 0).unwrap();
12981336
let rate_limiter_event =
@@ -1308,9 +1346,10 @@ mod tests {
13081346
fn test_tx_rate_limiter_handling() {
13091347
let mut event_manager = EventManager::new().unwrap();
13101348
let mut net = Net::default_net(TestMutators::default());
1311-
let mem_clone = net.mem.clone();
1312-
let (rxq, txq) = Net::virtqueues(&mem_clone);
1349+
let mem = Net::default_guest_memory();
1350+
let (rxq, txq) = Net::virtqueues(&mem);
13131351
net.assign_queues(rxq.create_queue(), txq.create_queue());
1352+
net.activate(mem.clone()).unwrap();
13141353

13151354
net.tx_rate_limiter = RateLimiter::new(0, None, 0, 0, None, 0).unwrap();
13161355
let rate_limiter_event =
@@ -1327,9 +1366,10 @@ mod tests {
13271366
fn test_bandwidth_rate_limiter() {
13281367
let mut event_manager = EventManager::new().unwrap();
13291368
let mut net = Net::default_net(TestMutators::default());
1330-
let mem_clone = net.mem.clone();
1331-
let (rxq, txq) = Net::virtqueues(&mem_clone);
1369+
let mem = Net::default_guest_memory();
1370+
let (rxq, txq) = Net::virtqueues(&mem);
13321371
net.assign_queues(rxq.create_queue(), txq.create_queue());
1372+
net.activate(mem.clone()).unwrap();
13331373

13341374
let daddr = 0x2000;
13351375
assert!(daddr > txq.end().0);
@@ -1445,9 +1485,10 @@ mod tests {
14451485
fn test_ops_rate_limiter() {
14461486
let mut event_manager = EventManager::new().unwrap();
14471487
let mut net = Net::default_net(TestMutators::default());
1448-
let mem_clone = net.mem.clone();
1449-
let (rxq, txq) = Net::virtqueues(&mem_clone);
1488+
let mem = Net::default_guest_memory();
1489+
let (rxq, txq) = Net::virtqueues(&mem);
14501490
net.assign_queues(rxq.create_queue(), txq.create_queue());
1491+
net.activate(mem.clone()).unwrap();
14511492

14521493
let daddr = 0x2000;
14531494
assert!(daddr > txq.end().0);
@@ -1564,9 +1605,10 @@ mod tests {
15641605
#[test]
15651606
fn test_patch_rate_limiters() {
15661607
let mut net = Net::default_net(TestMutators::default());
1567-
let mem_clone = net.mem.clone();
1568-
let (rxq, txq) = Net::virtqueues(&mem_clone);
1608+
let mem = Net::default_guest_memory();
1609+
let (rxq, txq) = Net::virtqueues(&mem);
15691610
net.assign_queues(rxq.create_queue(), txq.create_queue());
1611+
net.activate(mem.clone()).unwrap();
15701612

15711613
net.rx_rate_limiter = RateLimiter::new(10, None, 10, 2, None, 2).unwrap();
15721614
net.tx_rate_limiter = RateLimiter::new(10, None, 10, 2, None, 2).unwrap();
@@ -1600,9 +1642,10 @@ mod tests {
16001642
// Regression test for https://github.com/firecracker-microvm/firecracker/issues/1436 .
16011643
let mut event_manager = EventManager::new().unwrap();
16021644
let mut net = Net::default_net(TestMutators::default());
1603-
let mem_clone = net.mem.clone();
1604-
let (rxq, txq) = Net::virtqueues(&mem_clone);
1645+
let mem = Net::default_guest_memory();
1646+
let (rxq, txq) = Net::virtqueues(&mem);
16051647
net.assign_queues(rxq.create_queue(), txq.create_queue());
1648+
net.activate(mem.clone()).unwrap();
16061649

16071650
let daddr = 0x2000;
16081651
assert!(daddr > txq.end().0);
@@ -1626,9 +1669,10 @@ mod tests {
16261669
#[test]
16271670
fn test_virtio_device() {
16281671
let mut net = Net::default_net(TestMutators::default());
1629-
let mem_clone = net.mem.clone();
1630-
let (rxq, txq) = Net::virtqueues(&mem_clone);
1672+
let mem = Net::default_guest_memory();
1673+
let (rxq, txq) = Net::virtqueues(&mem);
16311674
net.assign_queues(rxq.create_queue(), txq.create_queue());
1675+
net.activate(mem.clone()).unwrap();
16321676

16331677
// Test queues count (TX and RX).
16341678
let queues = net.queues();

0 commit comments

Comments
 (0)