Skip to content

Commit 5d08eae

Browse files
committed
draft
1 parent 1d5ee0e commit 5d08eae

File tree

6 files changed

+530
-97
lines changed

6 files changed

+530
-97
lines changed

src/vmm/src/devices/virtio/net/tap.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,17 @@ pub mod tests {
241241
generated::ifreq__bindgen_ty_1::default().ifrn_name.len()
242242
});
243243

244-
// Empty name - The tap should be named "tap0" by default
244+
// Empty name - The tap should be named by the kernel (e.g., "tap0", "tap1", etc.)
245245
let tap = Tap::open_named("").unwrap();
246-
assert_eq!(b"tap0\0\0\0\0\0\0\0\0\0\0\0\0", &tap.if_name);
247-
assert_eq!("tap0", tap.if_name_as_str());
246+
let tap_name_str = tap.if_name_as_str();
247+
248+
// Check that it starts with "tap" and the remainder is numeric.
249+
assert!(
250+
Regex::new(r"^tap\d+$").unwrap().is_match(tap_name_str),
251+
"Generated tap name '{}' does not match expected pattern",
252+
tap_name_str
253+
);
254+
248255

249256
// Test using '%d' to have the kernel assign an unused name,
250257
// and that we correctly copy back that generated name

src/vmm/src/devices/virtio/rng/device.rs

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use aws_lc_rs::rand;
99
use vm_memory::GuestMemoryError;
1010
use vmm_sys_util::eventfd::EventFd;
1111

12-
use super::metrics::METRICS;
12+
use super::metrics::EntropyMetricsPerDevice;
1313
use super::{RNG_NUM_QUEUES, RNG_QUEUE};
1414
use crate::devices::DeviceError;
1515
use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice};
@@ -113,14 +113,15 @@ impl Entropy {
113113
}
114114

115115
fn handle_one(&mut self) -> Result<u32, EntropyError> {
116+
let global = EntropyMetricsPerDevice::alloc("global".to_string());
116117
// If guest provided us with an empty buffer just return directly
117118
if self.buffer.is_empty() {
118119
return Ok(0);
119120
}
120121

121122
let mut rand_bytes = vec![0; self.buffer.len() as usize];
122123
rand::fill(&mut rand_bytes).inspect_err(|_| {
123-
METRICS.host_rng_fails.inc();
124+
global.host_rng_fails.inc();
124125
})?;
125126

126127
// It is ok to unwrap here. We are writing `iovec.len()` bytes at offset 0.
@@ -129,12 +130,13 @@ impl Entropy {
129130
}
130131

131132
fn process_entropy_queue(&mut self) {
133+
let global = EntropyMetricsPerDevice::alloc("global".to_string());
132134
let mut used_any = false;
133135
while let Some(desc) = self.queues[RNG_QUEUE].pop() {
134136
// This is safe since we checked in the event handler that the device is activated.
135137
let mem = self.device_state.mem().unwrap();
136138
let index = desc.index;
137-
METRICS.entropy_event_count.inc();
139+
global.entropy_event_count.inc();
138140

139141
// SAFETY: This descriptor chain points to a single `DescriptorChain` memory buffer,
140142
// no other `IoVecBufferMut` object points to the same `DescriptorChain` at the same
@@ -151,33 +153,33 @@ impl Entropy {
151153
// to handle once we do have budget.
152154
if !self.rate_limit_request(u64::from(self.buffer.len())) {
153155
debug!("entropy: throttling entropy queue");
154-
METRICS.entropy_rate_limiter_throttled.inc();
156+
global.entropy_rate_limiter_throttled.inc();
155157
self.queues[RNG_QUEUE].undo_pop();
156158
break;
157159
}
158160

159161
self.handle_one().unwrap_or_else(|err| {
160162
error!("entropy: {err}");
161-
METRICS.entropy_event_fails.inc();
163+
global.entropy_event_fails.inc();
162164
0
163165
})
164166
}
165167
Err(err) => {
166168
error!("entropy: Could not parse descriptor chain: {err}");
167-
METRICS.entropy_event_fails.inc();
169+
global.entropy_event_fails.inc();
168170
0
169171
}
170172
};
171173

172174
match self.queues[RNG_QUEUE].add_used(index, bytes) {
173175
Ok(_) => {
174176
used_any = true;
175-
METRICS.entropy_bytes.add(bytes.into());
177+
global.entropy_bytes.add(bytes.into());
176178
}
177179
Err(err) => {
178180
error!("entropy: Could not add used descriptor to queue: {err}");
179181
Self::rate_limit_replenish_request(&mut self.rate_limiter, bytes.into());
180-
METRICS.entropy_event_fails.inc();
182+
global.entropy_event_fails.inc();
181183
// If we are not able to add a buffer to the used queue, something
182184
// is probably seriously wrong, so just stop processing additional
183185
// buffers
@@ -189,33 +191,34 @@ impl Entropy {
189191
if used_any {
190192
self.signal_used_queue().unwrap_or_else(|err| {
191193
error!("entropy: {err:?}");
192-
METRICS.entropy_event_fails.inc()
194+
global.entropy_event_fails.inc()
193195
});
194196
}
195197
}
196198

197199
pub(crate) fn process_entropy_queue_event(&mut self) {
200+
let global = EntropyMetricsPerDevice::alloc("global".to_string());
198201
if let Err(err) = self.queue_events[RNG_QUEUE].read() {
199202
error!("Failed to read entropy queue event: {err}");
200-
METRICS.entropy_event_fails.inc();
203+
global.entropy_event_fails.inc();
201204
} else if !self.rate_limiter.is_blocked() {
202205
// We are not throttled, handle the entropy queue
203206
self.process_entropy_queue();
204207
} else {
205-
METRICS.rate_limiter_event_count.inc();
208+
global.rate_limiter_event_count.inc();
206209
}
207210
}
208211

209212
pub(crate) fn process_rate_limiter_event(&mut self) {
210-
METRICS.rate_limiter_event_count.inc();
213+
global.rate_limiter_event_count.inc();
211214
match self.rate_limiter.event_handler() {
212215
Ok(_) => {
213216
// There might be enough budget now to process entropy requests.
214217
self.process_entropy_queue();
215218
}
216219
Err(err) => {
217220
error!("entropy: Failed to handle rate-limiter event: {err:?}");
218-
METRICS.entropy_event_fails.inc();
221+
global.entropy_event_fails.inc();
219222
}
220223
}
221224
}
@@ -291,13 +294,15 @@ impl VirtioDevice for Entropy {
291294
}
292295

293296
fn activate(&mut self, mem: GuestMemoryMmap) -> Result<(), ActivateError> {
297+
let global = EntropyMetricsPerDevice::alloc("global".to_string());
298+
294299
for q in self.queues.iter_mut() {
295300
q.initialize(&mem)
296301
.map_err(ActivateError::QueueMemoryError)?;
297302
}
298303

299304
self.activate_event.write(1).map_err(|_| {
300-
METRICS.activate_fails.inc();
305+
global.activate_fails.inc();
301306
ActivateError::EventFd
302307
})?;
303308
self.device_state = DeviceState::Activated(mem);
@@ -454,6 +459,7 @@ mod tests {
454459

455460
#[test]
456461
fn test_entropy_event() {
462+
let global = EntropyMetricsPerDevice::alloc("global".to_string());
457463
let mem = create_virtio_mem();
458464
let mut th = VirtioTestHelper::<Entropy>::new(&mem, default_entropy());
459465

@@ -462,29 +468,29 @@ mod tests {
462468
// Add a read-only descriptor (this should fail)
463469
th.add_desc_chain(RNG_QUEUE, 0, &[(0, 64, 0)]);
464470

465-
let entropy_event_fails = METRICS.entropy_event_fails.count();
466-
let entropy_event_count = METRICS.entropy_event_count.count();
467-
let entropy_bytes = METRICS.entropy_bytes.count();
468-
let host_rng_fails = METRICS.host_rng_fails.count();
471+
let entropy_event_fails = global.entropy_event_fails.count();
472+
let entropy_event_count = global.entropy_event_count.count();
473+
let entropy_bytes = global.entropy_bytes.count();
474+
let host_rng_fails = global.host_rng_fails.count();
469475
assert_eq!(th.emulate_for_msec(100).unwrap(), 1);
470-
assert_eq!(METRICS.entropy_event_fails.count(), entropy_event_fails + 1);
471-
assert_eq!(METRICS.entropy_event_count.count(), entropy_event_count + 1);
472-
assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes);
473-
assert_eq!(METRICS.host_rng_fails.count(), host_rng_fails);
476+
assert_eq!(global.entropy_event_fails.count(), entropy_event_fails + 1);
477+
assert_eq!(global.entropy_event_count.count(), entropy_event_count + 1);
478+
assert_eq!(global.entropy_bytes.count(), entropy_bytes);
479+
assert_eq!(global.host_rng_fails.count(), host_rng_fails);
474480

475481
// Add two good descriptors
476482
th.add_desc_chain(RNG_QUEUE, 0, &[(1, 10, VIRTQ_DESC_F_WRITE)]);
477483
th.add_desc_chain(RNG_QUEUE, 100, &[(2, 20, VIRTQ_DESC_F_WRITE)]);
478484

479-
let entropy_event_fails = METRICS.entropy_event_fails.count();
480-
let entropy_event_count = METRICS.entropy_event_count.count();
481-
let entropy_bytes = METRICS.entropy_bytes.count();
482-
let host_rng_fails = METRICS.host_rng_fails.count();
485+
let entropy_event_fails = global.entropy_event_fails.count();
486+
let entropy_event_count = global.entropy_event_count.count();
487+
let entropy_bytes = global.entropy_bytes.count();
488+
let host_rng_fails = global.host_rng_fails.count();
483489
assert_eq!(th.emulate_for_msec(100).unwrap(), 1);
484-
assert_eq!(METRICS.entropy_event_fails.count(), entropy_event_fails);
485-
assert_eq!(METRICS.entropy_event_count.count(), entropy_event_count + 2);
486-
assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes + 30);
487-
assert_eq!(METRICS.host_rng_fails.count(), host_rng_fails);
490+
assert_eq!(global.entropy_event_fails.count(), entropy_event_fails);
491+
assert_eq!(global.entropy_event_count.count(), entropy_event_count + 2);
492+
assert_eq!(global.entropy_bytes.count(), entropy_bytes + 30);
493+
assert_eq!(global.host_rng_fails.count(), host_rng_fails);
488494

489495
th.add_desc_chain(
490496
RNG_QUEUE,
@@ -496,34 +502,36 @@ mod tests {
496502
],
497503
);
498504

499-
let entropy_event_fails = METRICS.entropy_event_fails.count();
500-
let entropy_event_count = METRICS.entropy_event_count.count();
501-
let entropy_bytes = METRICS.entropy_bytes.count();
502-
let host_rng_fails = METRICS.host_rng_fails.count();
505+
let entropy_event_fails = global.entropy_event_fails.count();
506+
let entropy_event_count = global.entropy_event_count.count();
507+
let entropy_bytes = global.entropy_bytes.count();
508+
let host_rng_fails = global.host_rng_fails.count();
503509
assert_eq!(th.emulate_for_msec(100).unwrap(), 1);
504-
assert_eq!(METRICS.entropy_event_fails.count(), entropy_event_fails);
505-
assert_eq!(METRICS.entropy_event_count.count(), entropy_event_count + 1);
506-
assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes + 512);
507-
assert_eq!(METRICS.host_rng_fails.count(), host_rng_fails);
510+
assert_eq!(global.entropy_event_fails.count(), entropy_event_fails);
511+
assert_eq!(global.entropy_event_count.count(), entropy_event_count + 1);
512+
assert_eq!(global.entropy_bytes.count(), entropy_bytes + 512);
513+
assert_eq!(global.host_rng_fails.count(), host_rng_fails);
508514
}
509515

510516
#[test]
511517
fn test_bad_rate_limiter_event() {
518+
let global = EntropyMetricsPerDevice::alloc("global".to_string());
512519
let mem = create_virtio_mem();
513520
let mut th = VirtioTestHelper::<Entropy>::new(&mem, default_entropy());
514521

515522
th.activate_device(&mem);
516523
let mut dev = th.device();
517524

518525
check_metric_after_block!(
519-
&METRICS.entropy_event_fails,
526+
&global.entropy_event_fails,
520527
1,
521528
dev.process_rate_limiter_event()
522529
);
523530
}
524531

525532
#[test]
526533
fn test_bandwidth_rate_limiter() {
534+
let global = EntropyMetricsPerDevice::alloc("global".to_string());
527535
let mem = create_virtio_mem();
528536
// Rate Limiter with 4000 bytes / sec allowance and no initial burst allowance
529537
let device = Entropy::new(RateLimiter::new(4000, 0, 1000, 0, 0, 0).unwrap()).unwrap();
@@ -535,7 +543,7 @@ mod tests {
535543
// buffer should be processed normally
536544
th.add_desc_chain(RNG_QUEUE, 0, &[(0, 4000, VIRTQ_DESC_F_WRITE)]);
537545
check_metric_after_block!(
538-
METRICS.entropy_bytes,
546+
global.entropy_bytes,
539547
4000,
540548
th.device().process_entropy_queue()
541549
);
@@ -551,12 +559,12 @@ mod tests {
551559
th.add_desc_chain(RNG_QUEUE, 0, &[(0, 4000, VIRTQ_DESC_F_WRITE)]);
552560
th.add_desc_chain(RNG_QUEUE, 1, &[(1, 1000, VIRTQ_DESC_F_WRITE)]);
553561
check_metric_after_block!(
554-
METRICS.entropy_bytes,
562+
global.entropy_bytes,
555563
4000,
556564
th.device().process_entropy_queue()
557565
);
558566
check_metric_after_block!(
559-
METRICS.entropy_rate_limiter_throttled,
567+
global.entropy_rate_limiter_throttled,
560568
1,
561569
th.device().process_entropy_queue()
562570
);
@@ -565,12 +573,13 @@ mod tests {
565573
// 250 msec should give enough time for replenishing 1000 bytes worth of tokens.
566574
// Give it an extra 100 ms just to be sure the timer event reaches us from the kernel.
567575
std::thread::sleep(Duration::from_millis(350));
568-
check_metric_after_block!(METRICS.entropy_bytes, 1000, th.emulate_for_msec(100));
576+
check_metric_after_block!(global.entropy_bytes, 1000, th.emulate_for_msec(100));
569577
assert!(!th.device().rate_limiter().is_blocked());
570578
}
571579

572580
#[test]
573581
fn test_ops_rate_limiter() {
582+
let global = EntropyMetricsPerDevice::alloc("global".to_string());
574583
let mem = create_virtio_mem();
575584
// Rate Limiter with unlimited bandwidth and allowance for 1 operation every 100 msec,
576585
// (10 ops/sec), without initial burst.
@@ -583,7 +592,7 @@ mod tests {
583592
// so this should succeed.
584593
th.add_desc_chain(RNG_QUEUE, 0, &[(0, 4000, VIRTQ_DESC_F_WRITE)]);
585594
check_metric_after_block!(
586-
METRICS.entropy_bytes,
595+
global.entropy_bytes,
587596
4000,
588597
th.device().process_entropy_queue()
589598
);
@@ -593,30 +602,30 @@ mod tests {
593602
std::thread::sleep(Duration::from_millis(1000));
594603

595604
// First one should succeed
596-
let entropy_bytes = METRICS.entropy_bytes.count();
605+
let entropy_bytes = global.entropy_bytes.count();
597606
th.add_desc_chain(RNG_QUEUE, 0, &[(0, 64, VIRTQ_DESC_F_WRITE)]);
598-
check_metric_after_block!(METRICS.entropy_bytes, 64, th.emulate_for_msec(100));
599-
assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes + 64);
607+
check_metric_after_block!(global.entropy_bytes, 64, th.emulate_for_msec(100));
608+
assert_eq!(global.entropy_bytes.count(), entropy_bytes + 64);
600609
// The rate limiter is not blocked yet.
601610
assert!(!th.device().rate_limiter().is_blocked());
602611
// But immediately asking another operation should block it because we have 1 op every 100
603612
// msec.
604613
th.add_desc_chain(RNG_QUEUE, 0, &[(0, 64, VIRTQ_DESC_F_WRITE)]);
605614
check_metric_after_block!(
606-
METRICS.entropy_rate_limiter_throttled,
615+
global.entropy_rate_limiter_throttled,
607616
1,
608617
th.emulate_for_msec(50)
609618
);
610619
// Entropy bytes count should not have increased.
611-
assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes + 64);
620+
assert_eq!(global.entropy_bytes.count(), entropy_bytes + 64);
612621
// After 100 msec (plus 50 msec for ensuring the event reaches us from the kernel), the
613622
// timer of the rate limiter should fire saying that there's now more tokens available
614623
check_metric_after_block!(
615-
METRICS.rate_limiter_event_count,
624+
global.rate_limiter_event_count,
616625
1,
617626
th.emulate_for_msec(150)
618627
);
619628
// The rate limiter event should have processed the pending buffer as well
620-
assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes + 128);
629+
assert_eq!(global.entropy_bytes.count(), entropy_bytes + 128);
621630
}
622631
}

0 commit comments

Comments
 (0)