@@ -14,7 +14,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
14
14
use utils:: ioctl:: { ioctl_with_mut_ref, ioctl_with_ref, ioctl_with_val} ;
15
15
use utils:: { ioctl_ioc_nr, ioctl_iow_nr} ;
16
16
17
- use crate :: devices:: virtio:: iovec:: IoVecBuffer ;
17
+ use crate :: devices:: virtio:: iovec:: { IoVecBuffer , IoVecBufferMut } ;
18
18
use crate :: devices:: virtio:: net:: gen;
19
19
#[ cfg( test) ]
20
20
use crate :: devices:: virtio:: net:: test_utils:: Mocks ;
@@ -185,8 +185,22 @@ impl Tap {
185
185
Ok ( ( ) )
186
186
}
187
187
188
+ /// Read an `IoVecBufferMut` from tap
189
+ pub ( crate ) fn read_iovec ( & self , buffer : & mut IoVecBufferMut ) -> Result < usize , IoError > {
190
+ let iovcnt = i32:: try_from ( buffer. iovec_count ( ) ) . unwrap ( ) ;
191
+ let iov = buffer. as_iovec_ptr ( ) ;
192
+
193
+ // SAFETY: `readv` is safe. Called with a valid tap fd, the iovec pointer and length
194
+ // is provide by the `IoVecBufferMut` implementation and we check the return value.
195
+ let ret = unsafe { libc:: readv ( self . tap_file . as_raw_fd ( ) , iov, iovcnt) } ;
196
+ if ret == -1 {
197
+ return Err ( IoError :: last_os_error ( ) ) ;
198
+ }
199
+ Ok ( usize:: try_from ( ret) . unwrap ( ) )
200
+ }
201
+
188
202
/// Write an `IoVecBuffer` to tap
189
- pub ( crate ) fn write_iovec ( & mut self , buffer : & IoVecBuffer ) -> Result < usize , IoError > {
203
+ pub ( crate ) fn write_iovec ( & self , buffer : & IoVecBuffer ) -> Result < usize , IoError > {
190
204
let iovcnt = i32:: try_from ( buffer. iovec_count ( ) ) . unwrap ( ) ;
191
205
let iov = buffer. as_iovec_ptr ( ) ;
192
206
@@ -323,6 +337,28 @@ pub mod tests {
323
337
) ;
324
338
}
325
339
340
+ #[ test]
341
+ fn test_read_iovec ( ) {
342
+ let tap = Tap :: open_named ( "" ) . unwrap ( ) ;
343
+ enable ( & tap) ;
344
+ let tap_traffic_simulator = TapTrafficSimulator :: new ( if_index ( & tap) ) ;
345
+
346
+ let packet = utils:: rand:: rand_alphanumerics ( PAYLOAD_SIZE ) ;
347
+ tap_traffic_simulator. push_tx_packet ( packet. as_bytes ( ) ) ;
348
+
349
+ let mut fragment1 = [ 0_u8 ; VNET_HDR_SIZE ] ;
350
+ let mut fragment2 = [ 0_u8 ; PAYLOAD_SIZE ] ;
351
+
352
+ let mut scattered =
353
+ IoVecBufferMut :: from ( vec ! [ fragment1. as_mut_slice( ) , fragment2. as_mut_slice( ) ] ) ;
354
+
355
+ assert_eq ! (
356
+ tap. read_iovec( & mut scattered) . unwrap( ) ,
357
+ PAYLOAD_SIZE + VNET_HDR_SIZE
358
+ ) ;
359
+ assert_eq ! ( fragment2, packet. as_bytes( ) ) ;
360
+ }
361
+
326
362
#[ test]
327
363
fn test_write ( ) {
328
364
let mut tap = Tap :: open_named ( "" ) . unwrap ( ) ;
@@ -345,7 +381,7 @@ pub mod tests {
345
381
346
382
#[ test]
347
383
fn test_write_iovec ( ) {
348
- let mut tap = Tap :: open_named ( "" ) . unwrap ( ) ;
384
+ let tap = Tap :: open_named ( "" ) . unwrap ( ) ;
349
385
enable ( & tap) ;
350
386
let tap_traffic_simulator = TapTrafficSimulator :: new ( if_index ( & tap) ) ;
351
387
0 commit comments