Skip to content

Commit 36acc34

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 <[email protected]> Signed-off-by: Babis Chalios <[email protected]>
1 parent 9ec5f19 commit 36acc34

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 {
@@ -252,7 +252,7 @@ pub struct Net {
252252
pub(crate) metrics: Arc<NetDeviceMetrics>,
253253

254254
tx_buffer: IoVecBuffer,
255-
rx_buffer: RxBuffers,
255+
pub(crate) rx_buffer: RxBuffers,
256256
}
257257

258258
impl Net {
@@ -453,7 +453,7 @@ impl Net {
453453
}
454454

455455
/// Parse available RX `DescriptorChains` from the queue
456-
fn parse_rx_descriptors(&mut self) {
456+
pub fn parse_rx_descriptors(&mut self) {
457457
// This is safe since we checked in the event handler that the device is activated.
458458
let mem = self.device_state.mem().unwrap();
459459
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::NET_NUM_QUEUES;
12+
use super::device::{Net, RxBuffers};
13+
use super::{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.
@@ -83,6 +102,7 @@ impl Persist<'_> for Net {
83102
guest_mac: self.guest_mac,
84103
},
85104
virtio_state: VirtioDeviceState::from_device(self),
105+
rx_buffers_state: RxBufferState::from_rx_buffers(&self.rx_buffer),
86106
}
87107
}
88108

@@ -130,6 +150,14 @@ impl Persist<'_> for Net {
130150

131151
if state.virtio_state.activated {
132152
net.device_state = DeviceState::Activated(constructor_args.mem);
153+
154+
// Recreate `Net::rx_buffer`. We do it by re-parsing the RX queue. We're temporarily
155+
// rolling back `next_avail` in the RX queue and call `parse_rx_descriptors`.
156+
net.queues[RX_INDEX].next_avail -= state.rx_buffers_state.parsed_descriptor_chains_nr;
157+
net.parse_rx_descriptors();
158+
net.rx_buffer
159+
.deferred_descriptor
160+
.clone_from(&state.rx_buffers_state.deferred_descriptor);
133161
}
134162

135163
Ok(net)

0 commit comments

Comments
 (0)