@@ -76,6 +76,8 @@ pub struct RxBuffer {
7676 pub iovecs : IovRingBuffer ,
7777 // Ring buffer of meta data about descriptor chains stored in the `iov_ring`.
7878 pub chain_infos : RingBuffer < ChainInfo > ,
79+ // Total capacity this buffer holds.
80+ pub total_capacity : u32 ,
7981 // Number of descriptor chains we have used to process packets.
8082 pub used_descriptors : u16 ,
8183}
@@ -87,6 +89,7 @@ impl RxBuffer {
8789 iovecs : IovRingBuffer :: new ( ) ?,
8890 chain_infos : RingBuffer :: new_with_size ( u32:: from ( FIRECRACKER_MAX_QUEUE_SIZE ) ) ,
8991 used_descriptors : 0 ,
92+ total_capacity : 0 ,
9093 } )
9194 }
9295
@@ -108,8 +111,12 @@ impl RxBuffer {
108111
109112 /// Returns a slice of underlying iovec for the all chains
110113 /// in the buffer.
111- pub fn all_chains_mut_slice ( & mut self ) -> & mut [ iovec ] {
112- self . iovecs . as_mut_slice ( )
114+ pub fn all_chains_mut_slice ( & mut self ) -> Option < & mut [ iovec ] > {
115+ if self . total_capacity < u32:: from ( u16:: MAX ) {
116+ None
117+ } else {
118+ Some ( self . iovecs . as_mut_slice ( ) )
119+ }
113120 }
114121
115122 /// Add a new `DescriptorChain` that we received from the RX queue in the buffer.
@@ -166,6 +173,7 @@ impl RxBuffer {
166173 chain_len,
167174 chain_capacity,
168175 } ) ;
176+ self . total_capacity += chain_capacity;
169177
170178 Ok ( ( ) )
171179 }
@@ -234,6 +242,7 @@ impl RxBuffer {
234242 . pop_front ( )
235243 . expect ( "This should never happen if write to the buffer succeded." ) ;
236244 self . iovecs . pop_front ( usize:: from ( iov_info. chain_len ) ) ;
245+ self . total_capacity -= iov_info. chain_capacity ;
237246
238247 if bytes_written <= iov_info. chain_capacity {
239248 write_used ( iov_info. head_index , bytes_written, rx_queue) ;
@@ -281,7 +290,7 @@ mod tests {
281290
282291 #[ test]
283292 fn test_rx_buffer_add_chain ( ) {
284- let mem = single_region_mem ( 65562 ) ;
293+ let mem = single_region_mem ( 65562 * 2 ) ;
285294 let rxq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 256 ) ;
286295 let mut queue = rxq. create_queue ( ) ;
287296
@@ -316,9 +325,10 @@ mod tests {
316325 ) ;
317326 }
318327
319- // 16 chains of len 1
328+ // 64 chains of len 1 and size 1024
329+ // in total 64K
320330 {
321- let chains = 16 ;
331+ let chains = 64 ;
322332 set_dtable_many_chains ( & rxq, chains) ;
323333 queue. next_avail = Wrapping ( 0 ) ;
324334 let mut buff = RxBuffer :: new ( ) . unwrap ( ) ;
@@ -328,7 +338,7 @@ mod tests {
328338 buff. add_chain ( & mem, desc) . unwrap ( ) ;
329339 }
330340 }
331- let slice = buff. all_chains_mut_slice ( ) ;
341+ let slice = buff. all_chains_mut_slice ( ) . unwrap ( ) ;
332342 for i in 0 ..chains {
333343 assert_eq ! (
334344 slice[ i] . iov_base as u64 ,
@@ -337,7 +347,7 @@ mod tests {
337347 ) ;
338348 assert_eq ! ( slice[ i] . iov_len, 1024 ) ;
339349 }
340- assert_eq ! ( buff. chain_infos. len( ) , 16 ) ;
350+ assert_eq ! ( buff. chain_infos. len( ) , chains as u32 ) ;
341351 for ( i, ci) in buff. chain_infos . items [ 0 ..16 ] . iter ( ) . enumerate ( ) {
342352 assert_eq ! (
343353 * ci,
@@ -406,11 +416,11 @@ mod tests {
406416
407417 #[ test]
408418 fn test_rx_buffer_write_mrg_buf ( ) {
409- let mem = single_region_mem ( 65562 ) ;
419+ let mem = single_region_mem ( 65562 * 2 ) ;
410420 let rxq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 256 ) ;
411421 let mut queue = rxq. create_queue ( ) ;
412422
413- set_dtable_many_chains ( & rxq, 2 ) ;
423+ set_dtable_many_chains ( & rxq, 64 ) ;
414424
415425 let mut buff = RxBuffer :: new ( ) . unwrap ( ) ;
416426 while let Some ( desc) = queue. pop ( ) {
@@ -421,7 +431,7 @@ mod tests {
421431 }
422432
423433 // Initially data should be all zeros
424- let slice = buff. all_chains_mut_slice ( ) ;
434+ let slice = buff. all_chains_mut_slice ( ) . unwrap ( ) ;
425435 let data_slice_before: & [ u8 ] =
426436 // SAFETY: safe as iovecs are verified on creation.
427437 unsafe { std:: slice:: from_raw_parts ( slice[ 0 ] . iov_base . cast ( ) , slice[ 0 ] . iov_len ) } ;
@@ -434,7 +444,7 @@ mod tests {
434444 // Write should hapepn to all 2 iovecs
435445 buff. write ( & [ 69 ; 2 * 1024 ] ) . unwrap ( ) ;
436446
437- let slice = buff. all_chains_mut_slice ( ) ;
447+ let slice = buff. all_chains_mut_slice ( ) . unwrap ( ) ;
438448 let data_slice_after: & [ u8 ] =
439449 // SAFETY: safe as iovecs are verified on creation.
440450 unsafe { std:: slice:: from_raw_parts ( slice[ 0 ] . iov_base . cast ( ) , slice[ 0 ] . iov_len ) } ;
0 commit comments