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