Skip to content

Commit 46862ad

Browse files
authored
Merge branch 'main' into small-error-cleanup
2 parents 8d289ab + 83a9a55 commit 46862ad

File tree

3 files changed

+58
-27
lines changed

3 files changed

+58
-27
lines changed

docs/kernel-policy.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ The guest kernel configs used in our validation pipelines can be found
3737
[here](../resources/guest_configs/) while a breakdown of the relevant guest
3838
kernel modules can be found in the next section.
3939

40+
We use these configurations to build microVM-specific kernels vended by Amazon
41+
Linux. microVM kernel source code is published in the Amazon Linux
42+
[linux repo](https://github.com/amazonlinux/linux) under tags in the form of
43+
`microvm-kernel-*`, e.g. 6.1.128-3.201.amazn2023 kernel can be found
44+
[here](https://github.com/amazonlinux/linux/tree/microvm-kernel-6.1.128-3.201.amzn2023).
45+
These kernels may have diverged from the equivalent mainline versions, as we
46+
often backport patches that we require for supporting Firecracker features not
47+
present in the kernel versions we officially support. As a result, kernel
48+
configurations found in this repo should be used to build exclusively the
49+
aforementioned Amazon Linux kernels. We do not guarantee that using these
50+
configurations to build upstream kernels, will work or produce usable kernel
51+
images.
52+
4053
## Guest kernel configuration items
4154

4255
The configuration items that may be relevant for Firecracker are:

src/firecracker/examples/uffd/uffd_utils.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::fs::File;
1010
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
1111
use std::os::unix::net::UnixStream;
1212
use std::ptr;
13+
use std::time::Duration;
1314

1415
use serde::{Deserialize, Serialize};
1516
use userfaultfd::{Error, Event, Uffd};
@@ -52,38 +53,41 @@ pub struct UffdHandler {
5253
}
5354

5455
impl UffdHandler {
56+
fn try_get_mappings_and_file(
57+
stream: &UnixStream,
58+
) -> Result<(String, Option<File>), std::io::Error> {
59+
let mut message_buf = vec![0u8; 1024];
60+
let (bytes_read, file) = stream.recv_with_fd(&mut message_buf[..])?;
61+
message_buf.resize(bytes_read, 0);
62+
63+
// We do not expect to receive non-UTF-8 data from Firecracker, so this is probably
64+
// an error we can't recover from. Just immediately abort
65+
let body = String::from_utf8(message_buf.clone()).unwrap_or_else(|_| {
66+
panic!(
67+
"Received body is not a utf-8 valid string. Raw bytes received: {message_buf:#?}"
68+
)
69+
});
70+
Ok((body, file))
71+
}
72+
5573
fn get_mappings_and_file(stream: &UnixStream) -> (String, File) {
5674
// Sometimes, reading from the stream succeeds but we don't receive any
5775
// UFFD descriptor. We don't really have a good understanding why this is
5876
// happening, but let's try to be a bit more robust and retry a few times
5977
// before we declare defeat.
6078
for _ in 1..=5 {
61-
let mut message_buf = vec![0u8; 1024];
62-
let (bytes_read, file) = match stream.recv_with_fd(&mut message_buf[..]) {
63-
Ok(res) => res,
64-
Err(err) => {
65-
println!("Could not receive message from stream: {err}");
66-
continue;
79+
match Self::try_get_mappings_and_file(stream) {
80+
Ok((body, Some(file))) => {
81+
return (body, file);
6782
}
68-
};
69-
message_buf.resize(bytes_read, 0);
70-
71-
// We do not expect to receive non-UTF-8 data from Firecracker, so this is probably
72-
// an error we can't recover from. Just immediately abort
73-
let body = String::from_utf8(message_buf.clone()).unwrap_or_else(|_| {
74-
panic!(
75-
"Received body is not a utf-8 valid string. Raw bytes received: \
76-
{message_buf:#?}"
77-
)
78-
});
79-
let file = match file {
80-
Some(file) => file,
81-
None => {
82-
println!("Did not receive Uffd from UDS. Received body: {body}");
83-
continue;
83+
Ok((body, None)) => {
84+
println!("Didn't receive UFFD over socket. We received: '{body}'. Retrying...");
8485
}
85-
};
86-
return (body, file);
86+
Err(err) => {
87+
println!("Could not get UFFD and mapping from Firecracker: {err}. Retrying...");
88+
}
89+
}
90+
std::thread::sleep(Duration::from_millis(100));
8791
}
8892

8993
panic!("Could not get UFFD and mappings after 5 retries");

tests/integration_tests/performance/test_snapshot_ab.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,12 @@ def test_restore_latency(
142142
@pytest.mark.parametrize("uffd_handler", [None, "on_demand", "fault_all"])
143143
@pytest.mark.parametrize("huge_pages", HugePagesConfig)
144144
def test_post_restore_latency(
145-
microvm_factory, rootfs, guest_kernel_linux_5_10, metrics, uffd_handler, huge_pages
145+
microvm_factory,
146+
rootfs,
147+
guest_kernel_linux_5_10,
148+
metrics,
149+
uffd_handler,
150+
huge_pages,
146151
):
147152
"""Collects latency metric of post-restore memory accesses done inside the guest"""
148153
if huge_pages != HugePagesConfig.NONE and uffd_handler is None:
@@ -190,11 +195,20 @@ def test_post_restore_latency(
190195

191196
@pytest.mark.nonci
192197
@pytest.mark.parametrize("huge_pages", HugePagesConfig)
198+
@pytest.mark.parametrize(
199+
("vcpus", "mem"), [(1, 128), (1, 1024), (2, 2048), (3, 4096), (4, 6144)]
200+
)
193201
def test_population_latency(
194-
microvm_factory, rootfs, guest_kernel_linux_5_10, metrics, huge_pages
202+
microvm_factory,
203+
rootfs,
204+
guest_kernel_linux_5_10,
205+
metrics,
206+
huge_pages,
207+
vcpus,
208+
mem,
195209
):
196210
"""Collects population latency metrics (e.g. how long it takes UFFD handler to fault in all memory)"""
197-
test_setup = SnapshotRestoreTest(mem=128, vcpus=1, huge_pages=huge_pages)
211+
test_setup = SnapshotRestoreTest(mem=mem, vcpus=vcpus, huge_pages=huge_pages)
198212
vm = test_setup.boot_vm(microvm_factory, guest_kernel_linux_5_10, rootfs)
199213

200214
metrics.set_dimensions(

0 commit comments

Comments
 (0)