@@ -13,6 +13,7 @@ use std::ops::Deref;
1313use std:: sync:: { Arc , Mutex } ;
1414
1515use libc:: { EAGAIN , iovec} ;
16+ use serde:: { Deserialize , Serialize } ;
1617use vmm_sys_util:: eventfd:: EventFd ;
1718
1819use super :: NET_QUEUE_MAX_SIZE ;
@@ -29,7 +30,7 @@ use crate::devices::virtio::iovec::{
2930 IoVecBuffer , IoVecBufferMut , IoVecError , ParsedDescriptorChain ,
3031} ;
3132use crate :: devices:: virtio:: net:: metrics:: { NetDeviceMetrics , NetMetricsPerDevice } ;
32- use crate :: devices:: virtio:: net:: tap:: Tap ;
33+ use crate :: devices:: virtio:: net:: tap:: { NetDevBackend , PasstBackend , Tap } ;
3334use crate :: devices:: virtio:: net:: {
3435 MAX_BUFFER_SIZE , NET_QUEUE_SIZES , NetError , NetQueue , RX_INDEX , TX_INDEX , generated,
3536} ;
@@ -49,6 +50,19 @@ use crate::vstate::memory::{ByteValued, GuestMemoryMmap};
4950
5051const FRAME_HEADER_MAX_LEN : usize = PAYLOAD_OFFSET + ETH_IPV4_FRAME_LEN ;
5152
53+ const PASST_VIRTIO_FEATURES : u64 =
54+ ( 1 << VIRTIO_F_VERSION_1 ) | ( 1 << VIRTIO_NET_F_MRG_RXBUF ) | ( 1 << VIRTIO_RING_F_EVENT_IDX ) ;
55+
56+ const TAP_VIRTIO_FEATURES : u64 = ( 1 << VIRTIO_NET_F_GUEST_CSUM )
57+ | ( 1 << VIRTIO_NET_F_CSUM )
58+ | ( 1 << VIRTIO_NET_F_GUEST_TSO4 )
59+ | ( 1 << VIRTIO_NET_F_GUEST_TSO6 )
60+ | ( 1 << VIRTIO_NET_F_GUEST_UFO )
61+ | ( 1 << VIRTIO_NET_F_HOST_TSO4 )
62+ | ( 1 << VIRTIO_NET_F_HOST_TSO6 )
63+ | ( 1 << VIRTIO_NET_F_HOST_UFO )
64+ | ( 1 << VIRTIO_F_VERSION_1 ) ;
65+
5266pub ( crate ) const fn vnet_hdr_len ( ) -> usize {
5367 mem:: size_of :: < virtio_net_hdr_v1 > ( )
5468}
@@ -60,6 +74,13 @@ const fn frame_hdr_len() -> usize {
6074 vnet_hdr_len ( ) + FRAME_HEADER_MAX_LEN
6175}
6276
77+ #[ derive( Debug , Clone , Serialize , Deserialize , Eq , PartialEq ) ]
78+ #[ serde( rename_all = "snake_case" ) ]
79+ pub enum NetDevBackendType {
80+ Passt ( String ) , // The string denotes the passt socket path
81+ Tap ( String ) , // The string denotes the tap device name
82+ }
83+
6384// Frames being sent/received through the network device model have a VNET header. This
6485// function returns a slice which holds the L2 frame bytes without this header.
6586fn frame_bytes_from_buf ( buf : & [ u8 ] ) -> Result < & [ u8 ] , NetError > {
@@ -237,7 +258,7 @@ pub struct Net {
237258 pub ( crate ) id : String ,
238259
239260 /// The backend for this device: a tap.
240- pub tap : Tap ,
261+ pub backend : Box < dyn NetDevBackend > ,
241262
242263 pub ( crate ) avail_features : u64 ,
243264 pub ( crate ) acked_features : u64 ,
@@ -269,24 +290,17 @@ pub struct Net {
269290
270291impl Net {
271292 /// Create a new virtio network device with the given TAP interface.
272- pub fn new_with_tap (
293+ pub fn new_with_backend (
273294 id : String ,
274- tap : Tap ,
295+ backend : Box < dyn NetDevBackend > ,
275296 guest_mac : Option < MacAddr > ,
276297 rx_rate_limiter : RateLimiter ,
277298 tx_rate_limiter : RateLimiter ,
278299 ) -> Result < Self , NetError > {
279- let mut avail_features = ( 1 << VIRTIO_NET_F_GUEST_CSUM )
280- | ( 1 << VIRTIO_NET_F_CSUM )
281- | ( 1 << VIRTIO_NET_F_GUEST_TSO4 )
282- | ( 1 << VIRTIO_NET_F_GUEST_TSO6 )
283- | ( 1 << VIRTIO_NET_F_GUEST_UFO )
284- | ( 1 << VIRTIO_NET_F_HOST_TSO4 )
285- | ( 1 << VIRTIO_NET_F_HOST_TSO6 )
286- | ( 1 << VIRTIO_NET_F_HOST_UFO )
287- | ( 1 << VIRTIO_F_VERSION_1 )
288- | ( 1 << VIRTIO_NET_F_MRG_RXBUF )
289- | ( 1 << VIRTIO_RING_F_EVENT_IDX ) ;
300+ let mut avail_features = match backend. save ( ) {
301+ NetDevBackendType :: Passt ( _) => PASST_VIRTIO_FEATURES ,
302+ NetDevBackendType :: Tap ( _) => TAP_VIRTIO_FEATURES ,
303+ } ;
290304
291305 let mut config_space = ConfigSpace :: default ( ) ;
292306 if let Some ( mac) = guest_mac {
@@ -305,7 +319,7 @@ impl Net {
305319
306320 Ok ( Net {
307321 id : id. clone ( ) ,
308- tap ,
322+ backend : backend ,
309323 avail_features,
310324 acked_features : 0u64 ,
311325 queues,
@@ -328,28 +342,37 @@ impl Net {
328342 /// Create a new virtio network device given the interface name.
329343 pub fn new (
330344 id : String ,
331- tap_if_name : & str ,
345+ backend_identifier : & str ,
332346 guest_mac : Option < MacAddr > ,
333347 rx_rate_limiter : RateLimiter ,
334348 tx_rate_limiter : RateLimiter ,
349+ backend_type : NetDevBackendType ,
335350 ) -> Result < Self , NetError > {
336- let tap = Tap :: open_named ( tap_if_name) . map_err ( NetError :: TapOpen ) ?;
337-
338351 let vnet_hdr_size = i32:: try_from ( vnet_hdr_len ( ) ) . unwrap ( ) ;
339- tap. set_vnet_hdr_size ( vnet_hdr_size)
340- . map_err ( NetError :: TapSetVnetHdrSize ) ?;
352+ let backend: Box < dyn NetDevBackend > = match backend_type {
353+ NetDevBackendType :: Passt ( path) => {
354+ // id is passed as the socket path in the case of socket backend
355+ Box :: new ( PasstBackend :: new ( path) . map_err ( |_| NetError :: SocketOpen ( ) ) ?)
356+ }
357+ NetDevBackendType :: Tap ( tap_if_name) => {
358+ let mut tap = Tap :: open_named ( & tap_if_name) . map_err ( NetError :: TapOpen ) ?;
359+ tap. set_vnet_hdr_size ( vnet_hdr_size)
360+ . map_err ( NetError :: TapSetVnetHdrSize ) ?;
361+ Box :: new ( tap)
362+ }
363+ } ;
341364
342- Self :: new_with_tap ( id, tap , guest_mac, rx_rate_limiter, tx_rate_limiter)
365+ Self :: new_with_backend ( id, backend , guest_mac, rx_rate_limiter, tx_rate_limiter)
343366 }
344367
345368 /// Provides the MAC of this net device.
346369 pub fn guest_mac ( & self ) -> Option < & MacAddr > {
347370 self . guest_mac . as_ref ( )
348371 }
349372
350- /// Provides the host IFACE name of this net device.
351- pub fn iface_name ( & self ) -> String {
352- self . tap . if_name_as_str ( ) . to_string ( )
373+ /// Provides the identifier of this device.
374+ pub fn identifier ( & self ) -> String {
375+ self . backend . identifier ( ) . to_string ( )
353376 }
354377
355378 /// Provides the MmdsNetworkStack of this net device.
@@ -499,7 +522,7 @@ impl Net {
499522 rate_limiter : & mut RateLimiter ,
500523 headers : & mut [ u8 ] ,
501524 frame_iovec : & IoVecBuffer ,
502- tap : & mut Tap ,
525+ backend : & mut Box < dyn NetDevBackend > ,
503526 guest_mac : Option < MacAddr > ,
504527 net_metrics : & NetDeviceMetrics ,
505528 ) -> Result < bool , NetError > {
@@ -573,7 +596,7 @@ impl Net {
573596 }
574597
575598 let _metric = net_metrics. tap_write_agg . record_latency_metrics ( ) ;
576- match Self :: write_tap ( tap , frame_iovec) {
599+ match Self :: write_backend ( backend , frame_iovec) {
577600 Ok ( _) => {
578601 let len = u64:: from ( frame_iovec. len ( ) ) ;
579602 net_metrics. tx_bytes_count . add ( len) ;
@@ -746,12 +769,16 @@ impl Net {
746769 break ;
747770 }
748771
772+ // where is the tx buffer allocated from ? does this mean we buffer this data in the firecracker
773+ // process memory ? do we not have this zero copy trick we did in vsock ?
774+ // expl: write whats in the tx buffer to the tap interface
775+ // but wait. when did we even fill the tx buffer ?
749776 let frame_consumed_by_mmds = Self :: write_to_mmds_or_tap (
750777 self . mmds_ns . as_mut ( ) ,
751778 & mut self . tx_rate_limiter ,
752779 & mut self . tx_frame_headers ,
753780 & self . tx_buffer ,
754- & mut self . tap ,
781+ & mut self . backend ,
755782 self . guest_mac ,
756783 & self . metrics ,
757784 )
@@ -839,15 +866,21 @@ impl Net {
839866 ///
840867 /// `self.rx_buffer` needs to have at least one descriptor chain parsed
841868 pub unsafe fn read_tap ( & mut self ) -> std:: io:: Result < usize > {
842- let slice = if self . has_feature ( VIRTIO_NET_F_MRG_RXBUF as u64 ) {
869+ // if we have the merge feature (evaluates to true) we get all chains
870+ // let slice = if self.has_feature(VIRTIO_NET_F_MRG_RXBUF as u64) {
871+
872+ let slice = if false {
843873 self . rx_buffer . all_chains_slice_mut ( )
844874 } else {
845875 self . rx_buffer . single_chain_slice_mut ( )
846876 } ;
847- self . tap . read_iovec ( slice)
877+ self . backend . read_iovec ( slice)
848878 }
849879
850- fn write_tap ( tap : & mut Tap , buf : & IoVecBuffer ) -> std:: io:: Result < usize > {
880+ fn write_backend (
881+ tap : & mut Box < dyn NetDevBackend > ,
882+ buf : & IoVecBuffer ,
883+ ) -> std:: io:: Result < usize > {
851884 tap. write_iovec ( buf)
852885 }
853886
@@ -1041,10 +1074,13 @@ impl VirtioDevice for Net {
10411074 }
10421075 }
10431076
1077+ // ammar: we should try to fully understand offload
10441078 let supported_flags: u32 = Net :: build_tap_offload_features ( self . acked_features ) ;
1045- self . tap
1046- . set_offload ( supported_flags)
1047- . map_err ( super :: super :: ActivateError :: TapSetOffload ) ?;
1079+ if let NetDevBackendType :: Tap ( _) = self . backend . save ( ) {
1080+ self . backend
1081+ . set_offload ( supported_flags)
1082+ . map_err ( super :: super :: ActivateError :: TapSetOffload ) ?;
1083+ }
10481084
10491085 self . rx_buffer . min_buffer_size = self . minimum_rx_buffer_size ( ) ;
10501086
0 commit comments