Skip to content

Commit 837e72c

Browse files
andrewlabchalios
authored andcommitted
Adding host device renaming for snapshot restore
In some scenarios it is not possible to use the jailer, especially in limited privilege environments where the security is external to firecracker itself. But in these cases a snapshot may have to use a different tap device than the one that it was using when it was snapshotted. Signed-off-by: Andrew Laucius <[email protected]> Signed-off-by: Babis Chalios <[email protected]>
1 parent 7c0dc1e commit 837e72c

File tree

6 files changed

+60
-3
lines changed

6 files changed

+60
-3
lines changed

src/firecracker/src/api_server/request/snapshot.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ fn parse_put_snapshot_load(body: &Body) -> Result<ParsedRequest, RequestError> {
105105
mem_backend,
106106
enable_diff_snapshots: snapshot_config.enable_diff_snapshots,
107107
resume_vm: snapshot_config.resume_vm,
108+
network_overrides: snapshot_config.network_overrides,
108109
};
109110

110111
// Construct the `ParsedRequest` object.

src/firecracker/swagger/firecracker.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,24 @@ definitions:
12161216
Type of snapshot to create. It is optional and by default, a full
12171217
snapshot is created.
12181218

1219+
NetworkOverride:
1220+
type: object
1221+
description:
1222+
Allows for changing the backing TAP device of a network interface
1223+
during snapshot restore.
1224+
required:
1225+
- iface_id
1226+
- host_dev_name
1227+
properties:
1228+
iface_id:
1229+
type: string
1230+
description:
1231+
The name of the interface to modify
1232+
host_dev_name:
1233+
type: string
1234+
description:
1235+
The new host device of the interface
1236+
12191237
SnapshotLoadParams:
12201238
type: object
12211239
description:
@@ -1247,6 +1265,12 @@ definitions:
12471265
type: boolean
12481266
description:
12491267
When set to true, the vm is also resumed if the snapshot load is successful.
1268+
network_overrides:
1269+
type: array
1270+
description: Network host device names to override
1271+
items:
1272+
$ref: "#/definitions/NetworkOverride"
1273+
12501274

12511275
TokenBucket:
12521276
type: object

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ impl RxBufferState {
5555
/// at snapshot.
5656
#[derive(Debug, Clone, Serialize, Deserialize)]
5757
pub struct NetState {
58-
id: String,
59-
tap_if_name: String,
58+
pub id: String,
59+
pub tap_if_name: String,
6060
rx_rate_limiter_state: RateLimiterState,
6161
tx_rate_limiter_state: RateLimiterState,
6262
/// The associated MMDS network stack.

src/vmm/src/persist.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,21 @@ pub fn restore_from_snapshot(
405405
params: &LoadSnapshotParams,
406406
vm_resources: &mut VmResources,
407407
) -> Result<Arc<Mutex<Vmm>>, RestoreFromSnapshotError> {
408-
let microvm_state = snapshot_state_from_file(&params.snapshot_path)?;
408+
let mut microvm_state = snapshot_state_from_file(&params.snapshot_path)?;
409+
for entry in &params.network_overrides {
410+
let net_devices = &mut microvm_state.device_states.net_devices;
411+
if let Some(device) = net_devices
412+
.iter_mut()
413+
.find(|x| x.device_state.id == entry.iface_id)
414+
{
415+
device
416+
.device_state
417+
.tap_if_name
418+
.clone_from(&entry.host_dev_name);
419+
} else {
420+
return Err(SnapshotStateFromFileError::UnknownNetworkDevice.into());
421+
}
422+
}
409423
let track_dirty_pages = params.enable_diff_snapshots;
410424

411425
let vcpu_count = microvm_state
@@ -480,6 +494,8 @@ pub enum SnapshotStateFromFileError {
480494
Meta(std::io::Error),
481495
/// Failed to load snapshot state from file: {0}
482496
Load(#[from] crate::snapshot::SnapshotError),
497+
/// Unknown Network Device.
498+
UnknownNetworkDevice,
483499
}
484500

485501
fn snapshot_state_from_file(

src/vmm/src/rpc_interface.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,7 @@ mod tests {
12691269
},
12701270
enable_diff_snapshots: false,
12711271
resume_vm: false,
1272+
network_overrides: vec![],
12721273
},
12731274
)));
12741275
check_unsupported(runtime_request(VmmAction::SetEntropyDevice(

src/vmm/src/vmm_config/snapshot.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ pub struct CreateSnapshotParams {
4747
pub mem_file_path: PathBuf,
4848
}
4949

50+
/// Allows for changing the mapping between tap devices and host devices
51+
/// during snapshot restore
52+
#[derive(Debug, PartialEq, Eq, Deserialize)]
53+
pub struct NetworkOverride {
54+
/// The index of the interface to modify
55+
pub iface_id: String,
56+
/// The new name of the interface to be assigned
57+
pub host_dev_name: String,
58+
}
59+
5060
/// Stores the configuration that will be used for loading a snapshot.
5161
#[derive(Debug, PartialEq, Eq)]
5262
pub struct LoadSnapshotParams {
@@ -60,6 +70,8 @@ pub struct LoadSnapshotParams {
6070
/// When set to true, the vm is also resumed if the snapshot load
6171
/// is successful.
6272
pub resume_vm: bool,
73+
/// The network devices to override on load.
74+
pub network_overrides: Vec<NetworkOverride>,
6375
}
6476

6577
/// Stores the configuration for loading a snapshot that is provided by the user.
@@ -82,6 +94,9 @@ pub struct LoadSnapshotConfig {
8294
/// Whether or not to resume the vm post snapshot load.
8395
#[serde(default)]
8496
pub resume_vm: bool,
97+
/// The network devices to override on load.
98+
#[serde(default)]
99+
pub network_overrides: Vec<NetworkOverride>,
85100
}
86101

87102
/// Stores the configuration used for managing snapshot memory.

0 commit comments

Comments
 (0)