Skip to content

Commit cb65529

Browse files
bchaliosShadowCurse
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: Egor Lazarchuk <yegorlz@amazon.co.uk> Signed-off-by: Babis Chalios <bchalios@amazon.es>
1 parent 6966144 commit cb65529

File tree

3 files changed

+41
-12
lines changed

3 files changed

+41
-12
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
#[cfg(not(kani))]
89
use smallvec::SmallVec;
910
use vm_memory::bitmap::Bitmap;
@@ -218,7 +219,7 @@ impl IoVecBuffer {
218219
}
219220
}
220221

221-
#[derive(Debug)]
222+
#[derive(Debug, Clone, Serialize, Deserialize)]
222223
pub struct ParsedDescriptorChain {
223224
pub head_index: u16,
224225
pub length: u32,
@@ -233,9 +234,9 @@ pub struct ParsedDescriptorChain {
233234
#[derive(Debug)]
234235
pub struct IoVecBufferMut {
235236
// container of the memory regions included in this IO vector
236-
vecs: IovDeque,
237+
pub vecs: IovDeque,
237238
// Total length of the IoVecBufferMut
238-
len: usize,
239+
pub len: usize,
239240
}
240241

241242
impl IoVecBufferMut {

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,16 @@ enum AddRxBufferError {
9999

100100
/// A map of all the memory the guest has provided us with for performing RX
101101
#[derive(Debug)]
102-
pub(crate) struct RxBuffers {
102+
pub struct RxBuffers {
103103
// minimum size of a usable buffer for doing RX
104-
min_buffer_size: u32,
104+
pub min_buffer_size: u32,
105105
// An [`IoVecBufferMut`] covering all the memory we have available for receiving network
106106
// frames.
107-
iovec: IoVecBufferMut,
107+
pub iovec: IoVecBufferMut,
108108
// A map of which part of the memory belongs to which `DescriptorChain` object
109-
parsed_descriptors: VecDeque<ParsedDescriptorChain>,
109+
pub parsed_descriptors: VecDeque<ParsedDescriptorChain>,
110110
// Buffers that we have used and they are ready to be given back to the guest.
111-
deferred_descriptor: Option<ParsedDescriptorChain>,
111+
pub deferred_descriptor: Option<ParsedDescriptorChain>,
112112
}
113113

114114
impl RxBuffers {
@@ -241,7 +241,7 @@ pub struct Net {
241241
pub(crate) metrics: Arc<NetDeviceMetrics>,
242242

243243
tx_buffer: IoVecBuffer,
244-
rx_buffer: RxBuffers,
244+
pub(crate) rx_buffer: RxBuffers,
245245
}
246246

247247
impl Net {
@@ -436,7 +436,7 @@ impl Net {
436436
}
437437

438438
/// Parse available RX `DescriptorChains` from the queue
439-
fn parse_rx_descriptors(&mut self) {
439+
pub fn parse_rx_descriptors(&mut self) {
440440
// This is safe since we checked in the event handler that the device is activated.
441441
let mem = self.device_state.mem().unwrap();
442442
let queue = &mut self.queues[RX_INDEX];

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)