@@ -19,7 +19,7 @@ use crate::devices::virtio::gen::virtio_blk::VIRTIO_F_VERSION_1;
19
19
use crate :: devices:: virtio:: gen:: virtio_net:: {
20
20
virtio_net_hdr_v1, VIRTIO_NET_F_CSUM , VIRTIO_NET_F_GUEST_CSUM , VIRTIO_NET_F_GUEST_TSO4 ,
21
21
VIRTIO_NET_F_GUEST_TSO6 , VIRTIO_NET_F_GUEST_UFO , VIRTIO_NET_F_HOST_TSO4 ,
22
- VIRTIO_NET_F_HOST_TSO6 , VIRTIO_NET_F_HOST_UFO , VIRTIO_NET_F_MAC ,
22
+ VIRTIO_NET_F_HOST_TSO6 , VIRTIO_NET_F_HOST_UFO , VIRTIO_NET_F_MAC , VIRTIO_NET_F_MRG_RXBUF ,
23
23
} ;
24
24
use crate :: devices:: virtio:: gen:: virtio_ring:: VIRTIO_RING_F_EVENT_IDX ;
25
25
use crate :: devices:: virtio:: iovec:: IoVecBuffer ;
@@ -149,6 +149,7 @@ impl Net {
149
149
| 1 << VIRTIO_NET_F_HOST_TSO6
150
150
| 1 << VIRTIO_NET_F_HOST_UFO
151
151
| 1 << VIRTIO_F_VERSION_1
152
+ | 1 << VIRTIO_NET_F_MRG_RXBUF
152
153
| 1 << VIRTIO_RING_F_EVENT_IDX ;
153
154
154
155
let mut config_space = ConfigSpace :: default ( ) ;
@@ -659,7 +660,11 @@ impl Net {
659
660
}
660
661
661
662
fn read_tap ( & mut self ) -> std:: io:: Result < usize > {
662
- self . tap . read_iovec ( self . rx_buffer . one_chain_mut_slice ( ) )
663
+ if self . has_feature ( u64:: from ( VIRTIO_NET_F_MRG_RXBUF ) ) {
664
+ self . tap . read_iovec ( self . rx_buffer . all_chains_mut_slice ( ) )
665
+ } else {
666
+ self . tap . read_iovec ( self . rx_buffer . one_chain_mut_slice ( ) )
667
+ }
663
668
}
664
669
665
670
/// Process a single RX queue event.
@@ -891,8 +896,8 @@ pub mod tests {
891
896
use crate :: devices:: virtio:: net:: rx_buffer:: ChainInfo ;
892
897
use crate :: devices:: virtio:: net:: test_utils:: test:: TestHelper ;
893
898
use crate :: devices:: virtio:: net:: test_utils:: {
894
- default_net, if_index, inject_tap_tx_frame, set_mac , NetEvent , NetQueue ,
895
- TapTrafficSimulator ,
899
+ default_net, if_index, inject_tap_tx_frame, mock_frame_set_num_buffers , set_mac , NetEvent ,
900
+ NetQueue , TapTrafficSimulator ,
896
901
} ;
897
902
use crate :: devices:: virtio:: net:: NET_QUEUE_SIZES ;
898
903
use crate :: devices:: virtio:: queue:: VIRTQ_DESC_F_WRITE ;
@@ -1077,10 +1082,9 @@ pub mod tests {
1077
1082
assert_eq ! ( th. rxq. used. idx. get( ) , 0 ) ;
1078
1083
}
1079
1084
1080
- #[ test]
1081
- fn test_rx_read_only_descriptor ( ) {
1082
- let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1083
- let mut th = TestHelper :: get_default ( & mem) ;
1085
+ fn rx_read_only_descriptor ( mut th : TestHelper ) {
1086
+ // let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1087
+ // let mut th = TestHelper::get_default(&mem);
1084
1088
th. activate_net ( ) ;
1085
1089
1086
1090
th. add_desc_chain (
@@ -1099,9 +1103,22 @@ pub mod tests {
1099
1103
}
1100
1104
1101
1105
#[ test]
1102
- fn test_rx_partial_write ( ) {
1106
+ fn test_rx_read_only_descriptor ( ) {
1107
+ let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1108
+ let th = TestHelper :: get_default ( & mem) ;
1109
+ rx_read_only_descriptor ( th) ;
1110
+ }
1111
+
1112
+ #[ test]
1113
+ fn test_rx_read_only_descriptor_mrg_buf ( ) {
1103
1114
let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1104
1115
let mut th = TestHelper :: get_default ( & mem) ;
1116
+ // VIRTIO_NET_F_MRG_RXBUF is not enabled by default
1117
+ th. net ( ) . acked_features = 1 << VIRTIO_NET_F_MRG_RXBUF ;
1118
+ rx_read_only_descriptor ( th) ;
1119
+ }
1120
+
1121
+ fn rx_partial_write ( mut th : TestHelper ) {
1105
1122
th. activate_net ( ) ;
1106
1123
1107
1124
// The descriptor chain is created so that the last descriptor doesn't fit in the
@@ -1123,9 +1140,22 @@ pub mod tests {
1123
1140
}
1124
1141
1125
1142
#[ test]
1126
- fn test_rx_retry ( ) {
1143
+ fn test_rx_partial_write ( ) {
1144
+ let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1145
+ let th = TestHelper :: get_default ( & mem) ;
1146
+ rx_partial_write ( th) ;
1147
+ }
1148
+
1149
+ #[ test]
1150
+ fn test_rx_partial_write_mrg_buf ( ) {
1127
1151
let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1128
1152
let mut th = TestHelper :: get_default ( & mem) ;
1153
+ // VIRTIO_NET_F_MRG_RXBUF is not enabled by default
1154
+ th. net ( ) . acked_features = 1 << VIRTIO_NET_F_MRG_RXBUF ;
1155
+ rx_partial_write ( th) ;
1156
+ }
1157
+
1158
+ fn rx_retry ( mut th : TestHelper ) {
1129
1159
th. activate_net ( ) ;
1130
1160
1131
1161
// Even though too short descriptor chains are also
@@ -1175,9 +1205,22 @@ pub mod tests {
1175
1205
}
1176
1206
1177
1207
#[ test]
1178
- fn test_rx_complex_desc_chain ( ) {
1208
+ fn test_rx_retry ( ) {
1209
+ let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1210
+ let th = TestHelper :: get_default ( & mem) ;
1211
+ rx_retry ( th) ;
1212
+ }
1213
+
1214
+ #[ test]
1215
+ fn test_rx_retry_mrg_buf ( ) {
1179
1216
let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1180
1217
let mut th = TestHelper :: get_default ( & mem) ;
1218
+ // VIRTIO_NET_F_MRG_RXBUF is not enabled by default
1219
+ th. net ( ) . acked_features = 1 << VIRTIO_NET_F_MRG_RXBUF ;
1220
+ rx_retry ( th) ;
1221
+ }
1222
+
1223
+ fn rx_complex_desc_chain ( mut th : TestHelper ) {
1181
1224
th. activate_net ( ) ;
1182
1225
1183
1226
// Create a valid Rx avail descriptor chain with multiple descriptors.
@@ -1214,9 +1257,22 @@ pub mod tests {
1214
1257
}
1215
1258
1216
1259
#[ test]
1217
- fn test_rx_multiple_frames ( ) {
1260
+ fn test_rx_complex_desc_chain ( ) {
1261
+ let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1262
+ let th = TestHelper :: get_default ( & mem) ;
1263
+ rx_complex_desc_chain ( th) ;
1264
+ }
1265
+
1266
+ #[ test]
1267
+ fn test_rx_complex_desc_chain_mrg_buf ( ) {
1218
1268
let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1219
1269
let mut th = TestHelper :: get_default ( & mem) ;
1270
+ // VIRTIO_NET_F_MRG_RXBUF is not enabled by default
1271
+ th. net ( ) . acked_features = 1 << VIRTIO_NET_F_MRG_RXBUF ;
1272
+ rx_complex_desc_chain ( th) ;
1273
+ }
1274
+
1275
+ fn rx_multiple_frames ( mut th : TestHelper ) {
1220
1276
th. activate_net ( ) ;
1221
1277
1222
1278
// Create 2 valid Rx avail descriptor chains. Each one has enough space to fit the
@@ -1257,6 +1313,67 @@ pub mod tests {
1257
1313
th. rxq . dtable [ 3 ] . check_data ( & [ 0 ; 500 ] ) ;
1258
1314
}
1259
1315
1316
+ #[ test]
1317
+ fn test_rx_multiple_frames ( ) {
1318
+ let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1319
+ let th = TestHelper :: get_default ( & mem) ;
1320
+ rx_multiple_frames ( th) ;
1321
+ }
1322
+
1323
+ #[ test]
1324
+ fn test_rx_multiple_frames_mrg_buf ( ) {
1325
+ let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1326
+ let mut th = TestHelper :: get_default ( & mem) ;
1327
+ // VIRTIO_NET_F_MRG_RXBUF is not enabled by default
1328
+ th. net ( ) . acked_features = 1 << VIRTIO_NET_F_MRG_RXBUF ;
1329
+ rx_multiple_frames ( th) ;
1330
+ }
1331
+
1332
+ #[ test]
1333
+ fn test_rx_multiple_frames_mrg ( ) {
1334
+ let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
1335
+ let mut th = TestHelper :: get_default ( & mem) ;
1336
+
1337
+ // VIRTIO_NET_F_MRG_RXBUF is not enabled by default
1338
+ th. net ( ) . acked_features = 1 << VIRTIO_NET_F_MRG_RXBUF ;
1339
+
1340
+ th. activate_net ( ) ;
1341
+
1342
+ // Create 2 valid avail descriptor chains. We will send
1343
+ // one packet that shuld be split amound these 2 chains.
1344
+ th. add_desc_chain (
1345
+ NetQueue :: Rx ,
1346
+ 0 ,
1347
+ & [ ( 0 , 100 , VIRTQ_DESC_F_WRITE ) , ( 1 , 100 , VIRTQ_DESC_F_WRITE ) ] ,
1348
+ ) ;
1349
+ th. add_desc_chain (
1350
+ NetQueue :: Rx ,
1351
+ 1000 ,
1352
+ & [ ( 2 , 100 , VIRTQ_DESC_F_WRITE ) , ( 3 , 100 , VIRTQ_DESC_F_WRITE ) ] ,
1353
+ ) ;
1354
+ // Inject frame into tap and run epoll.
1355
+ let mut frame = inject_tap_tx_frame ( & th. net ( ) , 400 ) ;
1356
+ mock_frame_set_num_buffers ( & mut frame, 2 ) ;
1357
+ check_metric_after_block ! (
1358
+ th. net( ) . metrics. rx_packets_count,
1359
+ 1 ,
1360
+ th. event_manager. run_with_timeout( 100 ) . unwrap( )
1361
+ ) ;
1362
+
1363
+ // Check that the frame wasn't deferred.
1364
+ assert ! ( !th. net( ) . rx_deferred_frame) ;
1365
+ // Check that the used queue has advanced.
1366
+ assert_eq ! ( th. rxq. used. idx. get( ) , 2 ) ;
1367
+ assert ! ( & th. net( ) . irq_trigger. has_pending_irq( IrqType :: Vring ) ) ;
1368
+ // Check that the frame was written successfully into both descriptor chains.
1369
+ th. rxq . check_used_elem ( 0 , 0 , 200 ) ;
1370
+ th. rxq . check_used_elem ( 1 , 2 , 200 ) ;
1371
+ th. rxq . dtable [ 0 ] . check_data ( & frame[ 0 ..100 ] ) ;
1372
+ th. rxq . dtable [ 1 ] . check_data ( & frame[ 100 ..200 ] ) ;
1373
+ th. rxq . dtable [ 2 ] . check_data ( & frame[ 200 ..300 ] ) ;
1374
+ th. rxq . dtable [ 3 ] . check_data ( & frame[ 300 ..400 ] ) ;
1375
+ }
1376
+
1260
1377
#[ test]
1261
1378
fn test_tx_missing_queue_signal ( ) {
1262
1379
let mem = single_region_mem ( 2 * MAX_BUFFER_SIZE ) ;
0 commit comments