@@ -167,40 +167,39 @@ impl NetDevBackend for PasstBackend {
167167 fn read_iovec ( & mut self , buffer : & mut [ libc:: iovec ] ) -> Result < usize , IoError > {
168168 let iov = buffer. as_mut_ptr ( ) ;
169169
170- // offset the buffer by 12 to leave room for virtio header
170+ // the frame data goes into guest buffer offset by vnet_hdr_len to leave room for virtio header
171171 let data_iov = libc:: iovec {
172172 iov_base : unsafe { ( ( * iov) . iov_base as * mut u8 ) . add ( vnet_hdr_len ( ) ) as * mut _ } ,
173173 iov_len : unsafe { ( * iov) . iov_len - vnet_hdr_len ( ) } ,
174174 } ;
175175
176- // ammar: we are saying this is a "Socket" backend. not a passt backend. so should we really
177- // be having passt specific handling ? also on some level how well do we even understand passt ?
178- // is using it as in the test the standard way even ?
179- // create a 4 byte buffer, read the size that passt prepends into the packet and discard those
180- // bytes. we only care about the data packets
176+ // wire format from passt is: [vnet header (12)][length (4)][ethernet frame]
177+ // read vnet header and length prefix into throwaway buffers
178+ let mut vnet_buf = [ 0u8 ; 12 ] ;
181179 let mut len_buf = [ 0u8 ; 4 ] ;
182- let ret = unsafe {
183- libc:: read (
184- self . fd . as_raw_fd ( ) ,
185- len_buf. as_mut_ptr ( ) as * mut core:: ffi:: c_void ,
186- 4 ,
187- )
188- } ;
189- if ret == -1 {
190- return Err ( IoError :: last_os_error ( ) ) ;
191- }
192180
193- let _frame_len = u32:: from_be ( u32:: from_ne_bytes ( len_buf) ) ;
181+ let vnet_iov = libc:: iovec {
182+ iov_base : vnet_buf. as_mut_ptr ( ) as * mut _ ,
183+ iov_len : vnet_hdr_len ( ) ,
184+ } ;
185+ let len_iov = libc:: iovec {
186+ iov_base : len_buf. as_mut_ptr ( ) as * mut _ ,
187+ iov_len : 4 ,
188+ } ;
194189
195- let ret = unsafe { libc:: readv ( self . fd . as_raw_fd ( ) , & data_iov, 1 ) } ;
190+ // read vnet header + length prefix + ethernet frame in one syscall
191+ let mut iovs = [ vnet_iov, len_iov, data_iov] ;
192+ let ret = unsafe { libc:: readv ( self . fd . as_raw_fd ( ) , iovs. as_mut_ptr ( ) , 3 ) } ;
196193 if ret == -1 {
197194 return Err ( IoError :: last_os_error ( ) ) ;
198195 }
199196
200- // zero out the virtio header at the start
197+ // zero out the virtio header region at the start of the guest buffer
201198 unsafe { std:: ptr:: write_bytes ( ( * iov) . iov_base as * mut u8 , 0 , vnet_hdr_len ( ) ) } ;
202199
203- Ok ( usize:: try_from ( ret) . unwrap ( ) )
200+ // subtract the vnet header and length prefix bytes from the returned size
201+ // since the caller only cares about the ethernet frame size
202+ Ok ( usize:: try_from ( ret) . unwrap ( ) - vnet_hdr_len ( ) - 4 )
204203 }
205204
206205 fn write_iovec ( & mut self , buffer : & IoVecBuffer ) -> Result < usize , IoError > {
0 commit comments