@@ -1048,8 +1048,8 @@ pub mod tests {
10481048 } ;
10491049 use crate :: devices:: virtio:: net:: test_utils:: test:: TestHelper ;
10501050 use crate :: devices:: virtio:: net:: test_utils:: {
1051- default_net, if_index, inject_tap_tx_frame, set_mac , NetEvent , NetQueue , ReadTapMock ,
1052- TapTrafficSimulator , WriteTapMock ,
1051+ default_net, if_index, inject_tap_tx_frame, mock_frame_set_num_buffers , set_mac , NetEvent ,
1052+ NetQueue , ReadTapMock , TapTrafficSimulator , WriteTapMock ,
10531053 } ;
10541054 use crate :: devices:: virtio:: net:: NET_QUEUE_SIZES ;
10551055 use crate :: devices:: virtio:: queue:: VIRTQ_DESC_F_WRITE ;
@@ -1290,7 +1290,40 @@ pub mod tests {
12901290 }
12911291
12921292 #[ test]
1293- fn test_rx_partial_write ( ) {
1293+ fn test_rx_mrg_buf_multiple_short_writable_descriptors ( ) {
1294+ let mut th = TestHelper :: get_default ( ) ;
1295+ th. activate_net ( ) ;
1296+ th. net ( ) . tap . mocks . set_read_tap ( ReadTapMock :: TapFrame ) ;
1297+
1298+ // VIRTIO_NET_F_MRG_RXBUF is not enabled by default
1299+ th. net ( ) . acked_features = 1 << VIRTIO_NET_F_MRG_RXBUF ;
1300+
1301+ th. add_desc_chain ( NetQueue :: Rx , 0 , & [ ( 0 , 500 , VIRTQ_DESC_F_WRITE ) ] ) ;
1302+ th. add_desc_chain ( NetQueue :: Rx , 500 , & [ ( 1 , 500 , VIRTQ_DESC_F_WRITE ) ] ) ;
1303+
1304+ // There will be 2 heads used.
1305+ let mut frame = inject_tap_tx_frame ( & th. net ( ) , 1000 ) ;
1306+ mock_frame_set_num_buffers ( & mut frame, 2 ) ;
1307+
1308+ check_metric_after_block ! (
1309+ th. net( ) . metrics. rx_packets_count,
1310+ 1 ,
1311+ th. event_manager. run_with_timeout( 100 ) . unwrap( )
1312+ ) ;
1313+
1314+ assert_eq ! ( th. rxq. used. idx. get( ) , 2 ) ;
1315+ assert ! ( th. net( ) . irq_trigger. has_pending_irq( IrqType :: Vring ) ) ;
1316+ assert ! ( !th. net( ) . rx_deferred_frame) ;
1317+
1318+ th. rxq . check_used_elem ( 0 , 0 , 500 ) ;
1319+ th. rxq . check_used_elem ( 1 , 1 , 500 ) ;
1320+
1321+ th. rxq . dtable [ 0 ] . check_data ( & frame[ ..500 ] ) ;
1322+ th. rxq . dtable [ 1 ] . check_data ( & frame[ 500 ..] ) ;
1323+ }
1324+
1325+ #[ test]
1326+ fn test_rx_invalid_desc_chain ( ) {
12941327 let mut th = TestHelper :: get_default ( ) ;
12951328 th. activate_net ( ) ;
12961329
@@ -1312,6 +1345,79 @@ pub mod tests {
13121345 th. check_rx_queue_resume ( & frame) ;
13131346 }
13141347
1348+ #[ test]
1349+ fn test_rx_mrg_buf_invalid_desc_chain ( ) {
1350+ let mut th = TestHelper :: get_default ( ) ;
1351+ th. activate_net ( ) ;
1352+
1353+ // VIRTIO_NET_F_MRG_RXBUF is not enabled by default
1354+ th. net ( ) . acked_features = 1 << VIRTIO_NET_F_MRG_RXBUF ;
1355+
1356+ // The descriptor chain is created so that the last descriptor doesn't fit in the
1357+ // guest memory.
1358+ let offset = th. mem . last_addr ( ) . raw_value ( ) - th. data_addr ( ) - 300 ;
1359+ th. add_desc_chain (
1360+ NetQueue :: Rx ,
1361+ offset,
1362+ & [
1363+ ( 0 , 100 , VIRTQ_DESC_F_WRITE ) ,
1364+ ( 1 , 50 , VIRTQ_DESC_F_WRITE ) ,
1365+ ( 2 , 4096 , VIRTQ_DESC_F_WRITE ) ,
1366+ ] ,
1367+ ) ;
1368+ let frame = th. check_rx_deferred_frame ( 1000 ) ;
1369+ th. rxq . check_used_elem ( 0 , 0 , 0 ) ;
1370+
1371+ th. check_rx_queue_resume ( & frame) ;
1372+ }
1373+
1374+ #[ test]
1375+ fn test_rx_mrg_buf_partial_write ( ) {
1376+ let mut th = TestHelper :: get_default ( ) ;
1377+ th. activate_net ( ) ;
1378+ th. net ( ) . tap . mocks . set_read_tap ( ReadTapMock :: TapFrame ) ;
1379+
1380+ // VIRTIO_NET_F_MRG_RXBUF is not enabled by default
1381+ th. net ( ) . acked_features = 1 << VIRTIO_NET_F_MRG_RXBUF ;
1382+
1383+ // Add descriptor that is not big enough to store the
1384+ // whole packet.
1385+ th. add_desc_chain ( NetQueue :: Rx , 0 , & [ ( 0 , 500 , VIRTQ_DESC_F_WRITE ) ] ) ;
1386+
1387+ // There will be 2 heads used.
1388+ let mut frame = inject_tap_tx_frame ( & th. net ( ) , 1000 ) ;
1389+ mock_frame_set_num_buffers ( & mut frame, 2 ) ;
1390+
1391+ // For now only 1 descriptor chain is used,
1392+ // but the packet is not fully written yet.
1393+ check_metric_after_block ! (
1394+ th. net( ) . metrics. rx_packets_count,
1395+ 0 ,
1396+ th. event_manager. run_with_timeout( 100 ) . unwrap( )
1397+ ) ;
1398+ th. rxq . check_used_elem ( 0 , 0 , 500 ) ;
1399+
1400+ // The write was converted to partial write
1401+ assert ! ( th. net( ) . rx_partial_write. is_some( ) ) ;
1402+
1403+ // Continuing writing.
1404+ th. add_desc_chain ( NetQueue :: Rx , 500 , & [ ( 1 , 500 , VIRTQ_DESC_F_WRITE ) ] ) ;
1405+ check_metric_after_block ! (
1406+ th. net( ) . metrics. rx_packets_count,
1407+ 1 ,
1408+ th. event_manager. run_with_timeout( 100 ) . unwrap( )
1409+ ) ;
1410+ assert ! ( th. net( ) . rx_partial_write. is_none( ) ) ;
1411+ assert_eq ! ( th. rxq. used. idx. get( ) , 2 ) ;
1412+ assert ! ( th. net( ) . irq_trigger. has_pending_irq( IrqType :: Vring ) ) ;
1413+
1414+ th. rxq . check_used_elem ( 0 , 0 , 500 ) ;
1415+ th. rxq . check_used_elem ( 1 , 1 , 500 ) ;
1416+
1417+ th. rxq . dtable [ 0 ] . check_data ( & frame[ ..500 ] ) ;
1418+ th. rxq . dtable [ 1 ] . check_data ( & frame[ 500 ..] ) ;
1419+ }
1420+
13151421 #[ test]
13161422 fn test_rx_retry ( ) {
13171423 let mut th = TestHelper :: get_default ( ) ;
@@ -1363,6 +1469,62 @@ pub mod tests {
13631469 th. rxq . dtable [ 5 ] . check_data ( & frame) ;
13641470 }
13651471
1472+ #[ test]
1473+ fn test_rx_mrg_buf_retry ( ) {
1474+ let mut th = TestHelper :: get_default ( ) ;
1475+ th. activate_net ( ) ;
1476+ th. net ( ) . tap . mocks . set_read_tap ( ReadTapMock :: TapFrame ) ;
1477+
1478+ // VIRTIO_NET_F_MRG_RXBUF is not enabled by default
1479+ th. net ( ) . acked_features = 1 << VIRTIO_NET_F_MRG_RXBUF ;
1480+
1481+ // Add invalid descriptor chain - read only descriptor.
1482+ th. add_desc_chain (
1483+ NetQueue :: Rx ,
1484+ 0 ,
1485+ & [
1486+ ( 0 , 100 , VIRTQ_DESC_F_WRITE ) ,
1487+ ( 1 , 100 , 0 ) ,
1488+ ( 2 , 1000 , VIRTQ_DESC_F_WRITE ) ,
1489+ ] ,
1490+ ) ;
1491+ // Add valid descriptor chain but too short. This one will be used
1492+ // and the write will be converted to partial write.
1493+ th. add_desc_chain ( NetQueue :: Rx , 1200 , & [ ( 3 , 100 , VIRTQ_DESC_F_WRITE ) ] ) ;
1494+ // Add invalid descriptor chain - invalid memory offset.
1495+ // The partial write stated with previous descriptor should halt here.
1496+ th. add_desc_chain (
1497+ NetQueue :: Rx ,
1498+ th. mem . last_addr ( ) . raw_value ( ) ,
1499+ & [ ( 4 , 1000 , VIRTQ_DESC_F_WRITE ) ] ,
1500+ ) ;
1501+
1502+ // Add valid descriptor chain.
1503+ th. add_desc_chain ( NetQueue :: Rx , 1300 , & [ ( 5 , 1000 , VIRTQ_DESC_F_WRITE ) ] ) ;
1504+
1505+ // Inject frame to tap and run epoll.
1506+ let frame = inject_tap_tx_frame ( & th. net ( ) , 1000 ) ;
1507+ check_metric_after_block ! (
1508+ th. net( ) . metrics. rx_packets_count,
1509+ 1 ,
1510+ th. event_manager. run_with_timeout( 100 ) . unwrap( )
1511+ ) ;
1512+
1513+ // Check that the used queue has advanced.
1514+ assert_eq ! ( th. rxq. used. idx. get( ) , 4 ) ;
1515+ assert ! ( & th. net( ) . irq_trigger. has_pending_irq( IrqType :: Vring ) ) ;
1516+ // Check that the invalid descriptor chains have been discarded
1517+ th. rxq . check_used_elem ( 0 , 0 , 0 ) ;
1518+ th. rxq . check_used_elem ( 1 , 3 , 0 ) ;
1519+ th. rxq . check_used_elem ( 2 , 4 , 0 ) ;
1520+ // Check that the frame wasn't deferred.
1521+ assert ! ( !th. net( ) . rx_deferred_frame) ;
1522+ // Check that the frame has been written successfully to the valid Rx descriptor chain.
1523+ th. rxq
1524+ . check_used_elem ( 3 , 5 , frame. len ( ) . try_into ( ) . unwrap ( ) ) ;
1525+ th. rxq . dtable [ 5 ] . check_data ( & frame) ;
1526+ }
1527+
13661528 #[ test]
13671529 fn test_rx_complex_desc_chain ( ) {
13681530 let mut th = TestHelper :: get_default ( ) ;
0 commit comments