Skip to content

Commit 87e0b4b

Browse files
bchaliosroypat
authored andcommitted
net: support serializing RxBuffer
Now, that we pre-process the buffers that guest provides for performing RX, we need to save them in the VM state snapshot file, for networking to work correctly post snapshot resume. Implement Persist for RxBuffers and and plug them in the (de)serialization logic of the network device. Co-authored-by: Babis Chalios <[email protected]> Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent e03d4bc commit 87e0b4b

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

src/vmm/src/devices/virtio/iovec.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use std::io::ErrorKind;
55

66
use libc::{c_void, iovec, size_t};
7+
use serde::{Deserialize, Serialize};
78
use vm_memory::bitmap::Bitmap;
89
use vm_memory::{
910
GuestMemory, GuestMemoryError, ReadVolatile, VolatileMemoryError, VolatileSlice, WriteVolatile,
@@ -210,7 +211,7 @@ impl IoVecBuffer {
210211
}
211212
}
212213

213-
#[derive(Debug)]
214+
#[derive(Debug, Clone, Serialize, Deserialize)]
214215
pub struct ParsedDescriptorChain {
215216
pub head_index: u16,
216217
pub length: u32,
@@ -225,12 +226,12 @@ pub struct ParsedDescriptorChain {
225226
#[derive(Debug)]
226227
pub struct IoVecBufferMut {
227228
// container of the memory regions included in this IO vector
228-
vecs: IovDeque,
229+
pub vecs: IovDeque,
229230
// Total length of the IoVecBufferMut
230231
// We use `u32` here because we use this type in devices which
231232
// should not give us huge buffers. In any case this
232233
// value will not overflow as we explicitly check for this case.
233-
len: u32,
234+
pub len: u32,
234235
}
235236

236237
// SAFETY: `IoVecBufferMut` doesn't allow for interior mutability and no shared ownership is

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

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ use std::sync::{Arc, Mutex};
99

1010
use serde::{Deserialize, Serialize};
1111

12-
use super::device::Net;
13-
use super::{TapError, NET_NUM_QUEUES};
12+
use super::device::{Net, RxBuffers};
13+
use super::{TapError, NET_NUM_QUEUES, RX_INDEX};
1414
use crate::devices::virtio::device::DeviceState;
15+
use crate::devices::virtio::iovec::ParsedDescriptorChain;
1516
use crate::devices::virtio::persist::{PersistError as VirtioStateError, VirtioDeviceState};
1617
use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE;
1718
use crate::devices::virtio::TYPE_NET;
@@ -31,6 +32,23 @@ pub struct NetConfigSpaceState {
3132
guest_mac: Option<MacAddr>,
3233
}
3334

35+
/// Information about the parsed RX buffers
36+
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
37+
pub struct RxBufferState {
38+
// Number of iovecs we have parsed from the guest
39+
parsed_descriptor_chains_nr: u16,
40+
deferred_descriptor: Option<ParsedDescriptorChain>,
41+
}
42+
43+
impl RxBufferState {
44+
fn from_rx_buffers(rx_buffer: &RxBuffers) -> Self {
45+
RxBufferState {
46+
parsed_descriptor_chains_nr: rx_buffer.parsed_descriptors.len().try_into().unwrap(),
47+
deferred_descriptor: rx_buffer.deferred_descriptor.clone(),
48+
}
49+
}
50+
}
51+
3452
/// Information about the network device that are saved
3553
/// at snapshot.
3654
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -43,6 +61,7 @@ pub struct NetState {
4361
pub mmds_ns: Option<MmdsNetworkStackState>,
4462
config_space: NetConfigSpaceState,
4563
virtio_state: VirtioDeviceState,
64+
rx_buffers_state: RxBufferState,
4665
}
4766

4867
/// Auxiliary structure for creating a device when resuming from a snapshot.
@@ -85,6 +104,7 @@ impl Persist<'_> for Net {
85104
guest_mac: self.guest_mac,
86105
},
87106
virtio_state: VirtioDeviceState::from_device(self),
107+
rx_buffers_state: RxBufferState::from_rx_buffers(&self.rx_buffer),
88108
}
89109
}
90110

@@ -137,6 +157,14 @@ impl Persist<'_> for Net {
137157
.map_err(NetPersistError::TapSetOffload)?;
138158

139159
net.device_state = DeviceState::Activated(constructor_args.mem);
160+
161+
// Recreate `Net::rx_buffer`. We do it by re-parsing the RX queue. We're temporarily
162+
// rolling back `next_avail` in the RX queue and call `parse_rx_descriptors`.
163+
net.queues[RX_INDEX].next_avail -= state.rx_buffers_state.parsed_descriptor_chains_nr;
164+
net.parse_rx_descriptors();
165+
net.rx_buffer
166+
.deferred_descriptor
167+
.clone_from(&state.rx_buffers_state.deferred_descriptor);
140168
}
141169

142170
Ok(net)

0 commit comments

Comments
 (0)