Skip to content

Commit 27b725a

Browse files
committed
brand new
Signed-off-by: aerosouund <aerosound161@gmail.com>
1 parent c3ee1f9 commit 27b725a

8 files changed

Lines changed: 340 additions & 83 deletions

File tree

src/vmm/src/devices/virtio/net/device.rs

Lines changed: 70 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::ops::Deref;
1313
use std::sync::{Arc, Mutex};
1414

1515
use libc::{EAGAIN, iovec};
16+
use serde::{Deserialize, Serialize};
1617
use vmm_sys_util::eventfd::EventFd;
1718

1819
use super::NET_QUEUE_MAX_SIZE;
@@ -29,7 +30,7 @@ use crate::devices::virtio::iovec::{
2930
IoVecBuffer, IoVecBufferMut, IoVecError, ParsedDescriptorChain,
3031
};
3132
use 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};
3334
use 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

5051
const 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+
5266
pub(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.
6586
fn 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

270291
impl 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

src/vmm/src/devices/virtio/net/event_handler.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ impl Net {
4646
)) {
4747
error!("Failed to register tx queue event: {}", err);
4848
}
49+
let fd = &self.backend.as_raw_fd();
4950
if let Err(err) = ops.add(Events::with_data(
50-
&self.tap,
51+
fd,
5152
Self::PROCESS_TAP_RX,
5253
EventSet::IN | EventSet::EDGE_TRIGGERED,
5354
)) {

src/vmm/src/devices/virtio/net/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ pub enum NetQueue {
4747
pub enum NetError {
4848
/// Open tap device failed: {0}
4949
TapOpen(TapError),
50+
/// Socket backend opening failed
51+
SocketOpen(),
5052
/// Setting vnet header size failed: {0}
5153
TapSetVnetHdrSize(TapError),
5254
/// EventFd error: {0}

src/vmm/src/devices/virtio/net/persist.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize};
1111
use super::device::{Net, RxBuffers};
1212
use super::{NET_NUM_QUEUES, NET_QUEUE_MAX_SIZE, RX_INDEX, TapError};
1313
use crate::devices::virtio::device::{ActiveState, DeviceState, VirtioDeviceType};
14+
use crate::devices::virtio::net::device::NetDevBackendType;
1415
use crate::devices::virtio::persist::{PersistError as VirtioStateError, VirtioDeviceState};
1516
use crate::devices::virtio::transport::VirtioInterrupt;
1617
use crate::mmds::data_store::Mmds;
@@ -24,6 +25,7 @@ use crate::vstate::memory::GuestMemoryMmap;
2425

2526
/// Information about the network config's that are saved
2627
/// at snapshot.
28+
/// ammar: if i snapshot a passt vm and restore it, will i get the same mac?
2729
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
2830
pub struct NetConfigSpaceState {
2931
guest_mac: Option<MacAddr>,
@@ -41,6 +43,7 @@ pub struct NetState {
4143
pub mmds_ns: Option<MmdsNetworkStackState>,
4244
config_space: NetConfigSpaceState,
4345
pub virtio_state: VirtioDeviceState,
46+
pub backend_type: NetDevBackendType,
4447
}
4548

4649
/// Auxiliary structure for creating a device when resuming from a snapshot.
@@ -73,16 +76,18 @@ impl Persist<'_> for Net {
7376
type Error = NetPersistError;
7477

7578
fn save(&self) -> Self::State {
79+
// we need to figure out the underlying backend type here so we can persist properly
7680
NetState {
7781
id: self.id.clone(),
78-
tap_if_name: self.iface_name(),
82+
tap_if_name: self.identifier(),
7983
rx_rate_limiter_state: self.rx_rate_limiter.save(),
8084
tx_rate_limiter_state: self.tx_rate_limiter.save(),
8185
mmds_ns: self.mmds_ns.as_ref().map(|mmds| mmds.save()),
8286
config_space: NetConfigSpaceState {
8387
guest_mac: self.guest_mac,
8488
},
8589
virtio_state: VirtioDeviceState::from_device(self),
90+
backend_type: self.backend.save(),
8691
}
8792
}
8893

@@ -95,10 +100,11 @@ impl Persist<'_> for Net {
95100
let tx_rate_limiter = RateLimiter::restore((), &state.tx_rate_limiter_state)?;
96101
let mut net = Net::new(
97102
state.id.clone(),
98-
&state.tap_if_name,
103+
&state.tap_if_name, // make this not tap name. but something more generic
99104
state.config_space.guest_mac,
100105
rx_rate_limiter,
101106
tx_rate_limiter,
107+
NetDevBackendType::Tap(state.tap_if_name.clone()),
102108
)?;
103109

104110
// We trust the MMIODeviceManager::restore to pass us an MMDS data store reference if

0 commit comments

Comments
 (0)