@@ -9,7 +9,7 @@ use aws_lc_rs::rand;
99use vm_memory:: GuestMemoryError ;
1010use vmm_sys_util:: eventfd:: EventFd ;
1111
12- use super :: metrics:: METRICS ;
12+ use super :: metrics:: EntropyMetricsPerDevice ;
1313use super :: { RNG_NUM_QUEUES , RNG_QUEUE } ;
1414use crate :: devices:: DeviceError ;
1515use 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