Skip to content

Commit eda13d8

Browse files
ppennaCopilot
andcommitted
openvmm_helpers: number the snapshot's fields without gaps
The manifest skipped fields 9 and 10, which held the artifact digests of an earlier manifest version, and the machine contract skipped the clock fields of earlier versions and the policies of a retired second virtio-fs slot, so that no reader could mistake them. No reader of another version reads a version 2 manifest, so the manifest's fields now follow upstream's 1 to 7 without gaps, from 8 to 15, and the machine contract's run from 1 to 25, with the time contract and the CPU profile record at 11 and 12, where the clock fields were. The test that decoded the retired digests goes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 31d684a commit eda13d8

4 files changed

Lines changed: 27 additions & 62 deletions

File tree

‎Guide/src/dev_guide/snapshot_format.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ Key unsupported categories:
199199
## Extending the format
200200

201201
When adding new fields to `SnapshotManifest`, use the next available mesh
202-
tag number, never a retired one; the struct definitions list the retired tags.
202+
tag number.
203203
The protobuf encoding is forward-compatible: older readers will
204204
ignore unknown fields. However, removing or reordering existing fields is a
205205
breaking change. See [Save State](contrib/save-state.md) for the full set of

‎openvmm/openvmm_helpers/src/snapshot.rs‎

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,26 @@ pub struct SnapshotManifest {
4949
/// Length of `state.bin` in bytes.
5050
#[mesh(8)]
5151
pub state_size_bytes: u64,
52-
// Fields 9 and 10 held the artifact digests of manifest version 2. They
53-
// are retired, and their numbers are never reused.
5452
/// Authoritative machine composition for versioned machine profiles.
55-
#[mesh(11)]
53+
#[mesh(9)]
5654
pub machine_contract: Option<microvm::SnapshotMachineContract>,
5755
/// Snapshot format magic.
58-
#[mesh(12)]
56+
#[mesh(10)]
5957
pub format_magic: Vec<u8>,
6058
/// Version of the serialized VM saved-state schema.
61-
#[mesh(13)]
59+
#[mesh(11)]
6260
pub saved_state_schema_version: u32,
6361
/// Fully qualified protobuf root type stored in `state.bin`.
64-
#[mesh(14)]
62+
#[mesh(12)]
6563
pub saved_state_root_type: String,
6664
/// Sandbox capture tier. Empty for blockless microVM snapshots.
67-
#[mesh(15)]
65+
#[mesh(13)]
6866
pub snapshot_tier: String,
6967
/// `clone` for reusable artifacts or `resume` for single-use artifacts.
70-
#[mesh(16)]
68+
#[mesh(14)]
7169
pub restore_policy: String,
7270
/// Bitmask of configuration sections consumed before capture.
73-
#[mesh(17)]
71+
#[mesh(15)]
7472
pub consumed_config_sections: u32,
7573
}
7674

‎openvmm/openvmm_helpers/src/snapshot/format.rs‎

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ pub(super) fn validate_manifest_contents(manifest: &SnapshotManifest) -> anyhow:
151151
mod tests {
152152
use super::super::tests::test_manifest;
153153
use super::super::validate_manifest;
154-
use super::*;
155154

156155
#[test]
157156
fn other_versions_are_rejected_with_e_snapshot_version() {
@@ -193,32 +192,4 @@ mod tests {
193192
let err = validate_manifest(&manifest, "x86_64", 1024, 2, 4096).unwrap_err();
194193
assert!(err.to_string().contains("root type"));
195194
}
196-
197-
#[test]
198-
fn retired_digest_fields_are_ignored_when_decoding() {
199-
// A manifest encoded with fields 9 and 10 still decodes; the version
200-
// check rejects every manifest that set them.
201-
#[derive(mesh::payload::Protobuf)]
202-
#[mesh(package = "openvmm.snapshot")]
203-
struct WithDigests {
204-
#[mesh(1)]
205-
version: u32,
206-
#[mesh(9)]
207-
state_sha256: Vec<u8>,
208-
#[mesh(10)]
209-
memory_sha256: Vec<u8>,
210-
}
211-
let bytes = mesh::payload::encode(WithDigests {
212-
version: 2,
213-
state_sha256: vec![0xa5; SHA256_SIZE],
214-
memory_sha256: vec![0x5a; SHA256_SIZE],
215-
});
216-
let manifest: SnapshotManifest = mesh::payload::decode(&bytes).unwrap();
217-
assert_eq!(manifest.version, 2);
218-
let error = validate_manifest_header(&manifest).unwrap_err();
219-
assert!(
220-
error.to_string().contains("[E_SNAPSHOT_VERSION]"),
221-
"{error}"
222-
);
223-
}
224195
}

‎openvmm/openvmm_helpers/src/snapshot/microvm.rs‎

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -659,55 +659,51 @@ pub struct SnapshotMachineContract {
659659
/// Required host attachments.
660660
#[mesh(10)]
661661
pub attachments: Vec<SnapshotAttachment>,
662-
// Fields 11 to 15, 17, and 20 held the clock fields of manifest versions
663-
// 2 to 5. They are retired, and their numbers are never reused.
662+
/// The NVX time ABI time contract; required.
663+
#[mesh(11)]
664+
pub time: Option<openvmm_defs::time_abi::SnapshotTimeContract>,
665+
/// The NVX time ABI CPU profile record; required.
666+
#[mesh(12)]
667+
pub cpu_profile: Option<openvmm_defs::time_abi::SnapshotCpuProfile>,
664668
/// Version of the fixed cold-boot and memory layout.
665-
#[mesh(16)]
669+
#[mesh(13)]
666670
pub boot_layout_version: u32,
667671
/// Static identity of the optional microVM virtio-net device.
668-
#[mesh(18)]
672+
#[mesh(14)]
669673
pub microvm_network: Option<SnapshotMicrovmNetwork>,
670674
/// Guest-visible policy of the optional microVM virtio-fs device.
671-
#[mesh(19)]
675+
#[mesh(15)]
672676
pub microvm_filesystem: Option<SnapshotMicrovmFilesystem>,
673677
/// Fixed-role sandbox blocks in guest-visible order.
674-
#[mesh(21)]
678+
#[mesh(16)]
675679
pub microvm_sandbox_blocks: Vec<SnapshotMicrovmSandboxBlock>,
676680
/// Version of the reserved restore-attachable microVM virtio-fs slot.
677-
#[mesh(22)]
681+
#[mesh(17)]
678682
pub microvm_filesystem_slot_version: u32,
679683
/// Virtual processors online at boot, or zero when restore activation is disabled.
680-
#[mesh(23)]
684+
#[mesh(18)]
681685
pub boot_online_vp_count: u32,
682686
/// Virtio interrupt-delivery mode.
683-
#[mesh(24)]
687+
#[mesh(19)]
684688
pub virtio_interrupt_mode: String,
685689
/// Guest-physical base of the shared interrupt-status page, or zero when absent.
686-
#[mesh(25)]
690+
#[mesh(20)]
687691
pub virtio_shared_status_page_gpa: u64,
688692
/// Size of the shared interrupt-status page, or zero when absent.
689-
#[mesh(26)]
693+
#[mesh(21)]
690694
pub virtio_shared_status_page_size: u64,
691695
/// Restore-time memory expansion capability version, or zero when absent.
692-
#[mesh(27)]
696+
#[mesh(22)]
693697
pub memory_expansion_version: u32,
694698
/// Immutable maximum guest RAM size for restore-time expansion.
695-
#[mesh(28)]
699+
#[mesh(23)]
696700
pub memory_capacity_bytes: u64,
697701
/// Required alignment of every restore-time memory target and range.
698-
#[mesh(29)]
702+
#[mesh(24)]
699703
pub memory_block_size_bytes: u64,
700704
/// Canonical capacity ranges absent from the captured boot memory map.
701-
#[mesh(30)]
705+
#[mesh(25)]
702706
pub memory_expansion_ranges: Vec<SnapshotMemoryExpansionRange>,
703-
/// The NVX time ABI time contract; required.
704-
#[mesh(31)]
705-
pub time: Option<openvmm_defs::time_abi::SnapshotTimeContract>,
706-
/// The NVX time ABI CPU profile record; required.
707-
#[mesh(32)]
708-
pub cpu_profile: Option<openvmm_defs::time_abi::SnapshotCpuProfile>,
709-
// Field 33 held the policies of a second virtio-fs slot, which the
710-
// microVM no longer has. It is retired, and its number is never reused.
711707
}
712708

713709
impl SnapshotMachineContract {

0 commit comments

Comments
 (0)