@@ -127,8 +127,7 @@ pub struct Net {
127
127
128
128
rx_bytes_read : usize ,
129
129
rx_frame_buf : [ u8 ; MAX_BUFFER_SIZE ] ,
130
-
131
- tx_frame_headers : [ u8 ; frame_hdr_len ( ) ] ,
130
+ tx_frame_buf : [ u8 ; MAX_BUFFER_SIZE ] ,
132
131
133
132
pub ( crate ) irq_trigger : IrqTrigger ,
134
133
@@ -189,7 +188,7 @@ impl Net {
189
188
rx_deferred_frame : false ,
190
189
rx_bytes_read : 0 ,
191
190
rx_frame_buf : [ 0u8 ; MAX_BUFFER_SIZE ] ,
192
- tx_frame_headers : [ 0u8 ; frame_hdr_len ( ) ] ,
191
+ tx_frame_buf : [ 0u8 ; MAX_BUFFER_SIZE ] ,
193
192
irq_trigger : IrqTrigger :: new ( ) . map_err ( NetError :: EventFd ) ?,
194
193
config_space,
195
194
guest_mac,
@@ -438,37 +437,42 @@ impl Net {
438
437
fn write_to_mmds_or_tap (
439
438
mmds_ns : Option < & mut MmdsNetworkStack > ,
440
439
rate_limiter : & mut RateLimiter ,
441
- headers : & mut [ u8 ] ,
440
+ tx_frame_buf : & mut [ u8 ] ,
442
441
frame_iovec : & IoVecBuffer ,
443
442
tap : & mut Tap ,
444
443
guest_mac : Option < MacAddr > ,
445
444
net_metrics : & NetDeviceMetrics ,
446
445
) -> Result < bool , NetError > {
447
446
// Read the frame headers from the IoVecBuffer
448
- let max_header_len = headers . len ( ) ;
447
+ let max_header_len = frame_hdr_len ( ) ;
449
448
let header_len = frame_iovec
450
- . read_volatile_at ( & mut & mut * headers , 0 , max_header_len)
449
+ . read_volatile_at ( & mut & mut * tx_frame_buf , 0 , max_header_len)
451
450
. map_err ( |err| {
452
451
error ! ( "Received malformed TX buffer: {:?}" , err) ;
453
452
net_metrics. tx_malformed_frames . inc ( ) ;
454
453
NetError :: VnetHeaderMissing
455
454
} ) ?;
456
455
457
- let headers = frame_bytes_from_buf ( & headers[ ..header_len] ) . map_err ( |e| {
456
+ // First read just the headers of the frame so we can check if this is
457
+ // destined for MMDS.
458
+ let headers = frame_bytes_from_buf ( & tx_frame_buf[ ..header_len] ) . map_err ( |e| {
458
459
error ! ( "VNET headers missing in TX frame" ) ;
459
460
net_metrics. tx_malformed_frames . inc ( ) ;
460
461
e
461
462
} ) ?;
462
463
463
464
if let Some ( ns) = mmds_ns {
464
465
if ns. is_mmds_frame ( headers) {
465
- let mut frame = vec ! [ 0u8 ; frame_iovec. len( ) - vnet_hdr_len( ) ] ;
466
- // Ok to unwrap here, because we are passing a buffer that has the exact size
467
- // of the `IoVecBuffer` minus the VNET headers.
468
- frame_iovec
469
- . read_exact_volatile_at ( & mut frame, vnet_hdr_len ( ) )
470
- . unwrap ( ) ;
471
- let _ = ns. detour_frame ( & frame) ;
466
+ // This frame is destined for MMDS. So, now read the rest of the frame (if there's
467
+ // anything to read)
468
+ if frame_iovec. len ( ) > header_len {
469
+ // Ok to unwrap here, because we are passing a buffer that has the exact size
470
+ // of the `IoVecBuffer` minus the VNET headers.
471
+ frame_iovec
472
+ . read_exact_volatile_at ( & mut tx_frame_buf[ header_len..] , header_len)
473
+ . unwrap ( ) ;
474
+ }
475
+ let _ = ns. detour_frame ( & tx_frame_buf[ vnet_hdr_len ( ) ..] ) ;
472
476
METRICS . mmds . rx_accepted . inc ( ) ;
473
477
474
478
// MMDS frames are not accounted by the rate limiter.
@@ -607,6 +611,17 @@ impl Net {
607
611
continue ;
608
612
}
609
613
} ;
614
+
615
+ // We only handle frames that are up to MAX_BUFFER_SIZE
616
+ if buffer. len ( ) > MAX_BUFFER_SIZE {
617
+ error ! ( "net: received too big frame from driver" ) ;
618
+ self . metrics . tx_fails . inc ( ) ;
619
+ tx_queue
620
+ . add_used ( mem, head_index, 0 )
621
+ . map_err ( DeviceError :: QueueError ) ?;
622
+ continue ;
623
+ }
624
+
610
625
if !Self :: rate_limiter_consume_op ( & mut self . tx_rate_limiter , buffer. len ( ) as u64 ) {
611
626
tx_queue. undo_pop ( ) ;
612
627
self . metrics . tx_rate_limiter_throttled . inc ( ) ;
@@ -616,7 +631,7 @@ impl Net {
616
631
let frame_consumed_by_mmds = Self :: write_to_mmds_or_tap (
617
632
self . mmds_ns . as_mut ( ) ,
618
633
& mut self . tx_rate_limiter ,
619
- & mut self . tx_frame_headers ,
634
+ & mut self . tx_frame_buf [ ..buffer . len ( ) ] ,
620
635
& buffer,
621
636
& mut self . tap ,
622
637
self . guest_mac ,
0 commit comments