1use std::io;
5use std::ops::Deref;
6use std::sync::Arc;
7
8use aws_lc_rs::rand;
9use log::info;
10use vm_memory::GuestMemoryError;
11use vmm_sys_util::eventfd::EventFd;
12
13use super::metrics::METRICS;
14use super::{RNG_NUM_QUEUES, RNG_QUEUE};
15use crate::devices::DeviceError;
16use crate::devices::virtio::ActivateError;
17use crate::devices::virtio::device::{ActiveState, DeviceState, VirtioDevice};
18use crate::devices::virtio::generated::virtio_config::VIRTIO_F_VERSION_1;
19use crate::devices::virtio::generated::virtio_ids::VIRTIO_ID_RNG;
20use crate::devices::virtio::iov_deque::IovDequeError;
21use crate::devices::virtio::iovec::IoVecBufferMut;
22use crate::devices::virtio::queue::{FIRECRACKER_MAX_QUEUE_SIZE, InvalidAvailIdx, Queue};
23use crate::devices::virtio::transport::{VirtioInterrupt, VirtioInterruptType};
24use crate::impl_device_type;
25use crate::logger::{IncMetric, debug, error};
26use crate::rate_limiter::{RateLimiter, TokenType};
27use crate::vstate::memory::GuestMemoryMmap;
28
29pub const ENTROPY_DEV_ID: &str = "rng";
30
31#[derive(Debug, thiserror::Error, displaydoc::Display)]
32pub enum EntropyError {
33 EventFd(#[from] io::Error),
35 GuestMemory(#[from] GuestMemoryError),
37 Random(#[from] aws_lc_rs::error::Unspecified),
39 IovDeque(#[from] IovDequeError),
41}
42
43#[derive(Debug)]
44pub struct Entropy {
45 avail_features: u64,
47 acked_features: u64,
48 activate_event: EventFd,
49
50 device_state: DeviceState,
52 pub(crate) queues: Vec<Queue>,
53 queue_events: Vec<EventFd>,
54
55 rate_limiter: RateLimiter,
57
58 buffer: IoVecBufferMut,
59}
60
61impl Entropy {
62 pub fn new(rate_limiter: RateLimiter) -> Result<Self, EntropyError> {
63 let queues = vec![Queue::new(FIRECRACKER_MAX_QUEUE_SIZE); RNG_NUM_QUEUES];
64 Self::new_with_queues(queues, rate_limiter)
65 }
66
67 pub fn new_with_queues(
68 queues: Vec<Queue>,
69 rate_limiter: RateLimiter,
70 ) -> Result<Self, EntropyError> {
71 let activate_event = EventFd::new(libc::EFD_NONBLOCK)?;
72 let queue_events = (0..RNG_NUM_QUEUES)
73 .map(|_| EventFd::new(libc::EFD_NONBLOCK))
74 .collect::<Result<Vec<EventFd>, io::Error>>()?;
75
76 Ok(Self {
77 avail_features: 1 << VIRTIO_F_VERSION_1,
78 acked_features: 0u64,
79 activate_event,
80 device_state: DeviceState::Inactive,
81 queues,
82 queue_events,
83 rate_limiter,
84 buffer: IoVecBufferMut::new()?,
85 })
86 }
87
88 pub fn id(&self) -> &str {
89 ENTROPY_DEV_ID
90 }
91
92 fn signal_used_queue(&self) -> Result<(), DeviceError> {
93 self.interrupt_trigger()
94 .trigger(VirtioInterruptType::Queue(RNG_QUEUE.try_into().unwrap()))
95 .map_err(DeviceError::FailedSignalingIrq)
96 }
97
98 fn rate_limit_request(&mut self, bytes: u64) -> bool {
99 if !self.rate_limiter.consume(1, TokenType::Ops) {
100 return false;
101 }
102
103 if !self.rate_limiter.consume(bytes, TokenType::Bytes) {
104 self.rate_limiter.manual_replenish(1, TokenType::Ops);
105 return false;
106 }
107
108 true
109 }
110
111 fn rate_limit_replenish_request(rate_limiter: &mut RateLimiter, bytes: u64) {
112 rate_limiter.manual_replenish(1, TokenType::Ops);
113 rate_limiter.manual_replenish(bytes, TokenType::Bytes);
114 }
115
116 fn handle_one(&mut self) -> Result<u32, EntropyError> {
117 if self.buffer.is_empty() {
119 return Ok(0);
120 }
121
122 let mut rand_bytes = vec![0; self.buffer.len() as usize];
123 rand::fill(&mut rand_bytes).inspect_err(|_| {
124 METRICS.host_rng_fails.inc();
125 })?;
126
127 self.buffer.write_all_volatile_at(&rand_bytes, 0).unwrap();
129 Ok(self.buffer.len())
130 }
131
132 fn process_entropy_queue(&mut self) -> Result<(), InvalidAvailIdx> {
133 let mut used_any = false;
134 while let Some(desc) = self.queues[RNG_QUEUE].pop()? {
135 let mem = &self.device_state.active_state().unwrap().mem;
137 let index = desc.index;
138 METRICS.entropy_event_count.inc();
139
140 let bytes = match unsafe { self.buffer.load_descriptor_chain(mem, desc) } {
144 Ok(()) => {
145 debug!(
146 "entropy: guest request for {} bytes of entropy",
147 self.buffer.len()
148 );
149
150 if !self.rate_limit_request(u64::from(self.buffer.len())) {
154 debug!("entropy: throttling entropy queue");
155 METRICS.entropy_rate_limiter_throttled.inc();
156 self.queues[RNG_QUEUE].undo_pop();
157 break;
158 }
159
160 self.handle_one().unwrap_or_else(|err| {
161 error!("entropy: {err}");
162 METRICS.entropy_event_fails.inc();
163 0
164 })
165 }
166 Err(err) => {
167 error!("entropy: Could not parse descriptor chain: {err}");
168 METRICS.entropy_event_fails.inc();
169 0
170 }
171 };
172
173 match self.queues[RNG_QUEUE].add_used(index, bytes) {
174 Ok(_) => {
175 used_any = true;
176 METRICS.entropy_bytes.add(bytes.into());
177 }
178 Err(err) => {
179 error!("entropy: Could not add used descriptor to queue: {err}");
180 Self::rate_limit_replenish_request(&mut self.rate_limiter, bytes.into());
181 METRICS.entropy_event_fails.inc();
182 break;
186 }
187 }
188 }
189 self.queues[RNG_QUEUE].advance_used_ring_idx();
190
191 if used_any {
192 self.signal_used_queue().unwrap_or_else(|err| {
193 error!("entropy: {err:?}");
194 METRICS.entropy_event_fails.inc()
195 });
196 }
197
198 Ok(())
199 }
200
201 pub(crate) fn process_entropy_queue_event(&mut self) {
202 if let Err(err) = self.queue_events[RNG_QUEUE].read() {
203 error!("Failed to read entropy queue event: {err}");
204 METRICS.entropy_event_fails.inc();
205 } else if !self.rate_limiter.is_blocked() {
206 self.process_entropy_queue().unwrap()
208 } else {
209 METRICS.rate_limiter_event_count.inc();
210 }
211 }
212
213 pub(crate) fn process_rate_limiter_event(&mut self) {
214 METRICS.rate_limiter_event_count.inc();
215 match self.rate_limiter.event_handler() {
216 Ok(_) => {
217 self.process_entropy_queue().unwrap()
219 }
220 Err(err) => {
221 error!("entropy: Failed to handle rate-limiter event: {err:?}");
222 METRICS.entropy_event_fails.inc();
223 }
224 }
225 }
226
227 pub fn process_virtio_queues(&mut self) -> Result<(), InvalidAvailIdx> {
228 self.process_entropy_queue()
229 }
230
231 pub fn rate_limiter(&self) -> &RateLimiter {
232 &self.rate_limiter
233 }
234
235 pub(crate) fn set_avail_features(&mut self, features: u64) {
236 self.avail_features = features;
237 }
238
239 pub(crate) fn set_acked_features(&mut self, features: u64) {
240 self.acked_features = features;
241 }
242
243 pub(crate) fn set_activated(
244 &mut self,
245 mem: GuestMemoryMmap,
246 interrupt: Arc<dyn VirtioInterrupt>,
247 ) {
248 self.device_state = DeviceState::Activated(ActiveState { mem, interrupt });
249 }
250
251 pub(crate) fn activate_event(&self) -> &EventFd {
252 &self.activate_event
253 }
254}
255
256impl VirtioDevice for Entropy {
257 impl_device_type!(VIRTIO_ID_RNG);
258
259 fn queues(&self) -> &[Queue] {
260 &self.queues
261 }
262
263 fn queues_mut(&mut self) -> &mut [Queue] {
264 &mut self.queues
265 }
266
267 fn queue_events(&self) -> &[EventFd] {
268 &self.queue_events
269 }
270
271 fn interrupt_trigger(&self) -> &dyn VirtioInterrupt {
272 self.device_state
273 .active_state()
274 .expect("Device is not initialized")
275 .interrupt
276 .deref()
277 }
278
279 fn avail_features(&self) -> u64 {
280 self.avail_features
281 }
282
283 fn acked_features(&self) -> u64 {
284 self.acked_features
285 }
286
287 fn set_acked_features(&mut self, acked_features: u64) {
288 self.acked_features = acked_features;
289 }
290
291 fn read_config(&self, _offset: u64, mut _data: &mut [u8]) {}
292
293 fn write_config(&mut self, _offset: u64, _data: &[u8]) {}
294
295 fn is_activated(&self) -> bool {
296 self.device_state.is_activated()
297 }
298
299 fn activate(
300 &mut self,
301 mem: GuestMemoryMmap,
302 interrupt: Arc<dyn VirtioInterrupt>,
303 ) -> Result<(), ActivateError> {
304 for q in self.queues.iter_mut() {
305 q.initialize(&mem)
306 .map_err(ActivateError::QueueMemoryError)?;
307 }
308
309 self.activate_event.write(1).map_err(|_| {
310 METRICS.activate_fails.inc();
311 ActivateError::EventFd
312 })?;
313 self.device_state = DeviceState::Activated(ActiveState { mem, interrupt });
314 Ok(())
315 }
316
317 fn kick(&mut self) {
318 if self.is_activated() {
319 info!("kick entropy {}.", self.id());
320 self.process_virtio_queues();
321 }
322 }
323}
324
325#[cfg(test)]
326mod tests {
327 use std::time::Duration;
328
329 use super::*;
330 use crate::check_metric_after_block;
331 use crate::devices::virtio::device::VirtioDevice;
332 use crate::devices::virtio::queue::VIRTQ_DESC_F_WRITE;
333 use crate::devices::virtio::test_utils::test::{
334 VirtioTestDevice, VirtioTestHelper, create_virtio_mem,
335 };
336
337 impl VirtioTestDevice for Entropy {
338 fn set_queues(&mut self, queues: Vec<Queue>) {
339 self.queues = queues;
340 }
341
342 fn num_queues(&self) -> usize {
343 RNG_NUM_QUEUES
344 }
345 }
346
347 fn default_entropy() -> Entropy {
348 Entropy::new(RateLimiter::default()).unwrap()
349 }
350
351 #[test]
352 fn test_new() {
353 let entropy_dev = default_entropy();
354
355 assert_eq!(entropy_dev.avail_features(), 1 << VIRTIO_F_VERSION_1);
356 assert_eq!(entropy_dev.acked_features(), 0);
357 assert!(!entropy_dev.is_activated());
358 }
359
360 #[test]
361 fn test_id() {
362 let entropy_dev = default_entropy();
363 assert_eq!(entropy_dev.id(), ENTROPY_DEV_ID);
364 }
365
366 #[test]
367 fn test_device_type() {
368 let entropy_dev = default_entropy();
369 assert_eq!(entropy_dev.device_type(), VIRTIO_ID_RNG);
370 }
371
372 #[test]
373 fn test_read_config() {
374 let entropy_dev = default_entropy();
375 let mut config = vec![0; 10];
376
377 entropy_dev.read_config(0, &mut config);
378 assert_eq!(config, vec![0; 10]);
379
380 entropy_dev.read_config(1, &mut config);
381 assert_eq!(config, vec![0; 10]);
382
383 entropy_dev.read_config(2, &mut config);
384 assert_eq!(config, vec![0; 10]);
385
386 entropy_dev.read_config(1024, &mut config);
387 assert_eq!(config, vec![0; 10]);
388 }
389
390 #[test]
391 fn test_write_config() {
392 let mut entropy_dev = default_entropy();
393 let mut read_config = vec![0; 10];
394 let write_config = vec![42; 10];
395
396 entropy_dev.write_config(0, &write_config);
397 entropy_dev.read_config(0, &mut read_config);
398 assert_eq!(read_config, vec![0; 10]);
399
400 entropy_dev.write_config(1, &write_config);
401 entropy_dev.read_config(1, &mut read_config);
402 assert_eq!(read_config, vec![0; 10]);
403
404 entropy_dev.write_config(2, &write_config);
405 entropy_dev.read_config(2, &mut read_config);
406 assert_eq!(read_config, vec![0; 10]);
407
408 entropy_dev.write_config(1024, &write_config);
409 entropy_dev.read_config(1024, &mut read_config);
410 assert_eq!(read_config, vec![0; 10]);
411 }
412
413 #[test]
414 fn test_handle_one() {
415 let mem = create_virtio_mem();
416 let mut th = VirtioTestHelper::<Entropy>::new(&mem, default_entropy());
417
418 th.activate_device(&mem);
420
421 th.add_desc_chain(RNG_QUEUE, 0, &[(0, 64, 0)]);
423
424 th.add_desc_chain(RNG_QUEUE, 0, &[(1, 10, VIRTQ_DESC_F_WRITE)]);
426
427 th.add_desc_chain(RNG_QUEUE, 0, &[(2, 0, VIRTQ_DESC_F_WRITE)]);
429
430 let mut entropy_dev = th.device();
431
432 let desc = entropy_dev.queues_mut()[RNG_QUEUE].pop().unwrap().unwrap();
434 assert!(matches!(
435 unsafe { IoVecBufferMut::<256>::from_descriptor_chain(&mem, desc) },
437 Err(crate::devices::virtio::iovec::IoVecError::ReadOnlyDescriptor)
438 ));
439
440 let desc = entropy_dev.queues_mut()[RNG_QUEUE].pop().unwrap().unwrap();
442 entropy_dev.buffer = unsafe { IoVecBufferMut::from_descriptor_chain(&mem, desc).unwrap() };
444 entropy_dev.handle_one().unwrap();
445 }
446
447 #[test]
448 fn test_entropy_event() {
449 let mem = create_virtio_mem();
450 let mut th = VirtioTestHelper::<Entropy>::new(&mem, default_entropy());
451
452 th.activate_device(&mem);
453
454 th.add_desc_chain(RNG_QUEUE, 0, &[(0, 64, 0)]);
456
457 let entropy_event_fails = METRICS.entropy_event_fails.count();
458 let entropy_event_count = METRICS.entropy_event_count.count();
459 let entropy_bytes = METRICS.entropy_bytes.count();
460 let host_rng_fails = METRICS.host_rng_fails.count();
461 assert_eq!(th.emulate_for_msec(100).unwrap(), 1);
462 assert_eq!(METRICS.entropy_event_fails.count(), entropy_event_fails + 1);
463 assert_eq!(METRICS.entropy_event_count.count(), entropy_event_count + 1);
464 assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes);
465 assert_eq!(METRICS.host_rng_fails.count(), host_rng_fails);
466
467 th.add_desc_chain(RNG_QUEUE, 0, &[(1, 10, VIRTQ_DESC_F_WRITE)]);
469 th.add_desc_chain(RNG_QUEUE, 100, &[(2, 20, VIRTQ_DESC_F_WRITE)]);
470
471 let entropy_event_fails = METRICS.entropy_event_fails.count();
472 let entropy_event_count = METRICS.entropy_event_count.count();
473 let entropy_bytes = METRICS.entropy_bytes.count();
474 let host_rng_fails = METRICS.host_rng_fails.count();
475 assert_eq!(th.emulate_for_msec(100).unwrap(), 1);
476 assert_eq!(METRICS.entropy_event_fails.count(), entropy_event_fails);
477 assert_eq!(METRICS.entropy_event_count.count(), entropy_event_count + 2);
478 assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes + 30);
479 assert_eq!(METRICS.host_rng_fails.count(), host_rng_fails);
480
481 th.add_desc_chain(
482 RNG_QUEUE,
483 0,
484 &[
485 (3, 128, VIRTQ_DESC_F_WRITE),
486 (4, 128, VIRTQ_DESC_F_WRITE),
487 (5, 256, VIRTQ_DESC_F_WRITE),
488 ],
489 );
490
491 let entropy_event_fails = METRICS.entropy_event_fails.count();
492 let entropy_event_count = METRICS.entropy_event_count.count();
493 let entropy_bytes = METRICS.entropy_bytes.count();
494 let host_rng_fails = METRICS.host_rng_fails.count();
495 assert_eq!(th.emulate_for_msec(100).unwrap(), 1);
496 assert_eq!(METRICS.entropy_event_fails.count(), entropy_event_fails);
497 assert_eq!(METRICS.entropy_event_count.count(), entropy_event_count + 1);
498 assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes + 512);
499 assert_eq!(METRICS.host_rng_fails.count(), host_rng_fails);
500 }
501
502 #[test]
503 fn test_bad_rate_limiter_event() {
504 let mem = create_virtio_mem();
505 let mut th = VirtioTestHelper::<Entropy>::new(&mem, default_entropy());
506
507 th.activate_device(&mem);
508 let mut dev = th.device();
509
510 check_metric_after_block!(
511 &METRICS.entropy_event_fails,
512 1,
513 dev.process_rate_limiter_event()
514 );
515 }
516
517 #[test]
518 fn test_bandwidth_rate_limiter() {
519 let mem = create_virtio_mem();
520 let device = Entropy::new(RateLimiter::new(4000, 0, 1000, 0, 0, 0).unwrap()).unwrap();
522 let mut th = VirtioTestHelper::<Entropy>::new(&mem, device);
523
524 th.activate_device(&mem);
525
526 th.add_desc_chain(RNG_QUEUE, 0, &[(0, 4000, VIRTQ_DESC_F_WRITE)]);
529 check_metric_after_block!(
530 METRICS.entropy_bytes,
531 4000,
532 th.device().process_entropy_queue()
533 );
534 assert!(!th.device().rate_limiter.is_blocked());
535
536 th.device()
538 .rate_limiter
539 .manual_replenish(4000, TokenType::Bytes);
540
541 th.add_desc_chain(RNG_QUEUE, 0, &[(0, 4000, VIRTQ_DESC_F_WRITE)]);
544 th.add_desc_chain(RNG_QUEUE, 1, &[(1, 1000, VIRTQ_DESC_F_WRITE)]);
545 check_metric_after_block!(
546 METRICS.entropy_bytes,
547 4000,
548 th.device().process_entropy_queue()
549 );
550 check_metric_after_block!(
551 METRICS.entropy_rate_limiter_throttled,
552 1,
553 th.device().process_entropy_queue()
554 );
555 assert!(th.device().rate_limiter().is_blocked());
556
557 std::thread::sleep(Duration::from_millis(350));
560 check_metric_after_block!(METRICS.entropy_bytes, 1000, th.emulate_for_msec(100));
561 assert!(!th.device().rate_limiter().is_blocked());
562 }
563
564 #[test]
565 fn test_ops_rate_limiter() {
566 let mem = create_virtio_mem();
567 let device = Entropy::new(RateLimiter::new(0, 0, 0, 1, 0, 100).unwrap()).unwrap();
570 let mut th = VirtioTestHelper::<Entropy>::new(&mem, device);
571
572 th.activate_device(&mem);
573
574 th.add_desc_chain(RNG_QUEUE, 0, &[(0, 4000, VIRTQ_DESC_F_WRITE)]);
577 check_metric_after_block!(
578 METRICS.entropy_bytes,
579 4000,
580 th.device().process_entropy_queue()
581 );
582 assert!(!th.device().rate_limiter.is_blocked());
583
584 std::thread::sleep(Duration::from_millis(1000));
586
587 let entropy_bytes = METRICS.entropy_bytes.count();
589 th.add_desc_chain(RNG_QUEUE, 0, &[(0, 64, VIRTQ_DESC_F_WRITE)]);
590 check_metric_after_block!(METRICS.entropy_bytes, 64, th.emulate_for_msec(100));
591 assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes + 64);
592 assert!(!th.device().rate_limiter().is_blocked());
594 th.add_desc_chain(RNG_QUEUE, 0, &[(0, 64, VIRTQ_DESC_F_WRITE)]);
597 check_metric_after_block!(
598 METRICS.entropy_rate_limiter_throttled,
599 1,
600 th.emulate_for_msec(50)
601 );
602 assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes + 64);
604 check_metric_after_block!(
607 METRICS.rate_limiter_event_count,
608 1,
609 th.emulate_for_msec(150)
610 );
611 assert_eq!(METRICS.entropy_bytes.count(), entropy_bytes + 128);
613 }
614}