diff --git a/.buildkite/common.py b/.buildkite/common.py
index a2487aa1f44..a8913d5d6ef 100644
--- a/.buildkite/common.py
+++ b/.buildkite/common.py
@@ -13,14 +13,14 @@
import subprocess
from pathlib import Path
-DEFAULT_INSTANCES = {
- "c5n.metal": "x86_64", # Intel Skylake
- "m5n.metal": "x86_64", # Intel Cascade Lake
- "m6i.metal": "x86_64", # Intel Icelake
- "m6a.metal": "x86_64", # AMD Milan
- "m6g.metal": "aarch64", # Graviton2
- "m7g.metal": "aarch64", # Graviton3
-}
+DEFAULT_INSTANCES = [
+ "c5n.metal", # Intel Skylake
+ "m5n.metal", # Intel Cascade Lake
+ "m6i.metal", # Intel Icelake
+ "m6a.metal", # AMD Milan
+ "m6g.metal", # Graviton2
+ "m7g.metal", # Graviton3
+]
DEFAULT_PLATFORMS = [
("al2", "linux_5.10"),
@@ -28,6 +28,11 @@
]
+def get_arch_for_instance(instance):
+ """Return instance architecture"""
+ return "x86_64" if instance[2] != "g" else "aarch64"
+
+
def overlay_dict(base: dict, update: dict):
"""Overlay a dict over a base one"""
base = base.copy()
@@ -145,7 +150,7 @@ def __call__(self, parser, namespace, value, option_string=None):
"--instances",
required=False,
nargs="+",
- default=DEFAULT_INSTANCES.keys(),
+ default=DEFAULT_INSTANCES,
)
COMMON_PARSER.add_argument(
"--platforms",
@@ -180,16 +185,7 @@ def random_str(k: int):
def ab_revision_build(revision):
"""Generate steps for building an A/B-test revision"""
- # Copied from framework/ab_test. Double dollar signs needed for Buildkite (otherwise it will try to interpolate itself)
- return [
- f"commitish={revision}",
- f"if ! git cat-file -t $$commitish; then commitish=origin/{revision}; fi",
- "branch_name=tmp-$$commitish",
- "git branch $$branch_name $$commitish",
- f"git clone -b $$branch_name . build/{revision}",
- f"cd build/{revision} && ./tools/devtool -y build --release && cd -",
- "git branch -D $$branch_name",
- ]
+ return [f"./tools/devtool -y build --rev {revision} --release"]
def shared_build():
@@ -297,7 +293,7 @@ def _adapt_group(self, group):
step["command"] = prepend + step["command"]
if self.shared_build is not None:
step["depends_on"] = self.build_key(
- DEFAULT_INSTANCES[step["agents"]["instance"]]
+ get_arch_for_instance(step["agents"]["instance"])
)
return group
@@ -332,7 +328,7 @@ def build_group_per_arch(self, label, *args, **kwargs):
if set_key:
for step in grp["steps"]:
step["key"] = self.build_key(
- DEFAULT_INSTANCES[step["agents"]["instance"]]
+ get_arch_for_instance(step["agents"]["instance"])
)
return self.add_step(grp, depends_on_build=depends_on_build)
diff --git a/.buildkite/pipeline_cpu_template.py b/.buildkite/pipeline_cpu_template.py
index 2de782320c1..c8c5f75fa09 100755
--- a/.buildkite/pipeline_cpu_template.py
+++ b/.buildkite/pipeline_cpu_template.py
@@ -23,7 +23,7 @@ class BkStep(str, Enum):
cpu_template_test = {
"rdmsr": {
BkStep.COMMAND: [
- "tools/devtool -y test --no-build -- -m nonci -n4 --dist worksteal integration_tests/functional/test_cpu_features.py -k 'test_cpu_rdmsr' "
+ "tools/devtool -y test --no-build -- -m nonci -n4 --dist worksteal integration_tests/functional/test_cpu_features_x86_64.py -k 'test_cpu_rdmsr' "
],
BkStep.LABEL: "📖 rdmsr",
"instances": ["c5n.metal", "m5n.metal", "m6a.metal", "m6i.metal"],
@@ -34,13 +34,13 @@ class BkStep(str, Enum):
"tools/devtool -y test --no-build -- -m no_block_pr integration_tests/functional/test_cpu_template_helper.py -k test_guest_cpu_config_change",
],
BkStep.LABEL: "🖐️ fingerprint",
- "instances": DEFAULT_INSTANCES.keys(),
+ "instances": DEFAULT_INSTANCES,
"platforms": DEFAULT_PLATFORMS,
},
"cpuid_wrmsr": {
"snapshot": {
BkStep.COMMAND: [
- "tools/devtool -y test --no-build -- -m nonci -n4 --dist worksteal integration_tests/functional/test_cpu_features.py -k 'test_cpu_wrmsr_snapshot or test_cpu_cpuid_snapshot'",
+ "tools/devtool -y test --no-build -- -m nonci -n4 --dist worksteal integration_tests/functional/test_cpu_features_x86_64.py -k 'test_cpu_wrmsr_snapshot or test_cpu_cpuid_snapshot'",
"mkdir -pv tests/snapshot_artifacts_upload/{instance}_{os}_{kv}",
"sudo mv tests/snapshot_artifacts/* tests/snapshot_artifacts_upload/{instance}_{os}_{kv}",
],
@@ -52,7 +52,7 @@ class BkStep(str, Enum):
BkStep.COMMAND: [
"buildkite-agent artifact download tests/snapshot_artifacts_upload/{instance}_{os}_{kv}/**/* .",
"mv tests/snapshot_artifacts_upload/{instance}_{os}_{kv} tests/snapshot_artifacts",
- "tools/devtool -y test --no-build -- -m nonci -n4 --dist worksteal integration_tests/functional/test_cpu_features.py -k 'test_cpu_wrmsr_restore or test_cpu_cpuid_restore'",
+ "tools/devtool -y test --no-build -- -m nonci -n4 --dist worksteal integration_tests/functional/test_cpu_features_x86_64.py -k 'test_cpu_wrmsr_restore or test_cpu_cpuid_restore'",
],
BkStep.LABEL: "📸 load snapshot artifacts created on {instance} {snapshot_os} {snapshot_kv} to {restore_instance} {restore_os} {restore_kv}",
BkStep.TIMEOUT: 30,
diff --git a/.buildkite/pipeline_cross.py b/.buildkite/pipeline_cross.py
index ceb89d27f3d..d7cd261a3d0 100755
--- a/.buildkite/pipeline_cross.py
+++ b/.buildkite/pipeline_cross.py
@@ -21,10 +21,12 @@
instances_x86_64 = ["c5n.metal", "m5n.metal", "m6i.metal", "m6a.metal"]
instances_aarch64 = ["m7g.metal"]
commands = [
- "./tools/devtool -y sh ./tools/create_snapshot_artifact/main.py",
- "mkdir -pv snapshots/{instance}_{kv}",
- "sudo chown -Rc $USER: snapshot_artifacts",
- "mv -v snapshot_artifacts/* snapshots/{instance}_{kv}",
+ "./tools/devtool -y test --no-build -- -m nonci -n4 integration_tests/functional/test_snapshot_phase1.py",
+ # punch holes in mem snapshot tiles and tar them so they are preserved in S3
+ "find test_results/test_snapshot_phase1 -type f -name mem |xargs -P4 -t -n1 fallocate -d",
+ "mv -v test_results/test_snapshot_phase1 snapshot_artifacts",
+ "mkdir -pv snapshots",
+ "tar cSvf snapshots/{instance}_{kv}.tar snapshot_artifacts",
]
pipeline.build_group(
"📸 create snapshots",
@@ -80,10 +82,10 @@
k_val = pytest_keyword_for_instance.get(dst_instance, "")
step = {
"command": [
- f"buildkite-agent artifact download snapshots/{src_instance}_{src_kv}/* .",
- f"mv -v snapshots/{src_instance}_{src_kv} snapshot_artifacts",
+ f"buildkite-agent artifact download snapshots/{src_instance}_{src_kv}.tar .",
+ f"tar xSvf snapshots/{src_instance}_{src_kv}.tar",
*pipeline.devtool_test(
- pytest_opts=f"-m nonci {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py",
+ pytest_opts=f"-m nonci -n4 {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py",
),
],
"label": f"🎬 {src_instance} {src_kv} ➡️ {dst_instance} {dst_kv}",
diff --git a/.buildkite/pipeline_perf.py b/.buildkite/pipeline_perf.py
index 6f82c3c86d3..e8169bfb2cd 100755
--- a/.buildkite/pipeline_perf.py
+++ b/.buildkite/pipeline_perf.py
@@ -98,7 +98,9 @@
pytest_opts = ""
if REVISION_A:
devtool_opts += " --ab"
- pytest_opts = f"{ab_opts} run {REVISION_A} {REVISION_B} --test {test_path}"
+ pytest_opts = (
+ f"{ab_opts} run build/{REVISION_A}/ build/{REVISION_B} --test {test_path}"
+ )
else:
# Passing `-m ''` below instructs pytest to collect tests regardless of
# their markers (e.g. it will collect both tests marked as nonci, and
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 1d6da74ba72..e05f0c2ae15 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -15,16 +15,20 @@ Certificate of Origin and signing off your commits, please check
## PR Checklist
+- [ ] I have read and understand [CONTRIBUTING.md][3].
+- [ ] I have run `tools/devtool checkstyle` to verify that the PR passes the
+ automated style checks.
+- [ ] I have described what is done in these changes, why they are needed, and
+ how they are solving the problem in a clear and encompassing way.
+- [ ] I have updated any relevant documentation (both in code and in the docs)
+ in the PR.
+- [ ] I have mentioned all user-facing changes in `CHANGELOG.md`.
- [ ] If a specific issue led to this PR, this PR closes the issue.
-- [ ] The description of changes is clear and encompassing.
-- [ ] Any required documentation changes (code and docs) are included in this
- PR.
-- [ ] API changes follow the [Runbook for Firecracker API changes][2].
-- [ ] User-facing changes are mentioned in `CHANGELOG.md`.
-- [ ] All added/changed functionality is tested.
-- [ ] New `TODO`s link to an issue.
-- [ ] Commits meet
- [contribution quality standards](https://github.com/firecracker-microvm/firecracker/blob/main/CONTRIBUTING.md#contribution-quality-standards).
+- [ ] When making API changes, I have followed the
+ [Runbook for Firecracker API changes][2].
+- [ ] I have tested all new and changed functionalities in unit tests and/or
+ integration tests.
+- [ ] I have linked an issue to every new `TODO`.
______________________________________________________________________
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 188115bb448..7da89123eab 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,30 @@ and this project adheres to
### Added
+### Changed
+
+- [#4913](https://github.com/firecracker-microvm/firecracker/pull/4913): Removed
+ unnecessary fields (`max_connections` and `max_pending_resets`) from the
+ snapshot format, bumping the snapshot version to 5.0.0. Users need to
+ regenerate snapshots.
+
+### Deprecated
+
+### Removed
+
+### Fixed
+
+## \[1.10.1\]
+
+### Changed
+
+- [#4907](https://github.com/firecracker-microvm/firecracker/pull/4907): Bumped
+ the snapshot version to 4.0.0, so users need to regenerate snapshots.
+
+## \[1.10.0\]
+
+### Added
+
- [#4834](https://github.com/firecracker-microvm/firecracker/pull/4834): Add
`VIRTIO_NET_F_RX_MRGBUF` support to the `virtio-net` device. When this feature
is negotiated, guest `virtio-net` driver can perform more efficient memory
@@ -26,9 +50,17 @@ and this project adheres to
- [#4869](https://github.com/firecracker-microvm/firecracker/pull/4869): Added
support for Aarch64 systems which feature CPU caches with a number of sets
higher than `u16::MAX`.
+- [#4797](https://github.com/firecracker-microvm/firecracker/pull/4797),
+ [#4854](https://github.com/firecracker-microvm/firecracker/pull/4854): Added
+ GDB debugging support for a microVM guest kernel. Please see our
+ [GDB debugging documentation](docs/gdb-debugging.md) for more information.
### Changed
+- [#4844](https://github.com/firecracker-microvm/firecracker/pull/4844): Upgrade
+ `virtio-net` device to use `readv` syscall to avoid unnecessary memory copies
+ on RX path, increasing the RX performance.
+
### Deprecated
### Removed
diff --git a/Cargo.lock b/Cargo.lock
index f95d9c5ffb6..b3ad7e16b54 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -7,9 +7,9 @@ name = "acpi_tables"
version = "0.1.0"
dependencies = [
"displaydoc",
- "thiserror",
+ "thiserror 2.0.3",
"vm-memory",
- "zerocopy 0.8.6",
+ "zerocopy 0.8.10",
]
[[package]]
@@ -64,9 +64,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
-version = "0.6.15"
+version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -79,36 +79,36 @@ dependencies = [
[[package]]
name = "anstyle"
-version = "1.0.8"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
-version = "0.2.5"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
-version = "1.1.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.4"
+version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -125,11 +125,11 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "aws-lc-fips-sys"
-version = "0.12.13"
+version = "0.12.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf12b67bc9c5168f68655aadb2a12081689a58f1d9b1484705e4d1810ed6e4ac"
+checksum = "8671005a9c1e80bd3dc9aee84c5bfd594d32a3d645fdb56d5d9d5e26daa4c315"
dependencies = [
- "bindgen 0.69.4",
+ "bindgen 0.69.5",
"cc",
"cmake",
"dunce",
@@ -140,9 +140,9 @@ dependencies = [
[[package]]
name = "aws-lc-rs"
-version = "1.10.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d"
+checksum = "fe7c2840b66236045acd2607d5866e274380afd87ef99d6226e961e2cb47df45"
dependencies = [
"aws-lc-fips-sys",
"aws-lc-sys",
@@ -154,11 +154,11 @@ dependencies = [
[[package]]
name = "aws-lc-sys"
-version = "0.22.0"
+version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972"
+checksum = "ad3a619a9de81e1d7de1f1186dcba4506ed661a0e483d84410fdef0ee87b2f96"
dependencies = [
- "bindgen 0.69.4",
+ "bindgen 0.69.5",
"cc",
"cmake",
"dunce",
@@ -204,9 +204,9 @@ dependencies = [
[[package]]
name = "bindgen"
-version = "0.69.4"
+version = "0.69.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
+checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
dependencies = [
"bitflags 2.6.0",
"cexpr",
@@ -261,9 +261,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
-version = "1.1.31"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f"
+checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
dependencies = [
"jobserver",
"libc",
@@ -341,9 +341,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.20"
+version = "4.5.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
+checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
dependencies = [
"clap_builder",
"clap_derive",
@@ -360,9 +360,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.20"
+version = "4.5.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
+checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
dependencies = [
"anstream",
"anstyle",
@@ -384,9 +384,9 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.7.2"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
[[package]]
name = "clippy-tracing"
@@ -412,13 +412,13 @@ dependencies = [
[[package]]
name = "colorchoice"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "cpu-template-helper"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
dependencies = [
"clap",
"displaydoc",
@@ -426,16 +426,16 @@ dependencies = [
"log-instrument",
"serde",
"serde_json",
- "thiserror",
+ "thiserror 2.0.3",
"vmm",
"vmm-sys-util",
]
[[package]]
name = "cpufeatures"
-version = "0.2.14"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
+checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6"
dependencies = [
"libc",
]
@@ -606,7 +606,7 @@ dependencies = [
[[package]]
name = "firecracker"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
dependencies = [
"bincode",
"cargo_toml",
@@ -620,7 +620,7 @@ dependencies = [
"serde",
"serde_derive",
"serde_json",
- "thiserror",
+ "thiserror 2.0.3",
"timerfd",
"userfaultfd",
"utils",
@@ -636,9 +636,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "gdbstub"
-version = "0.7.2"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbcc892208d6998fb57e7c3e05883def66f8130924bba066beb0cfe71566a9f6"
+checksum = "31c683a9f13de31432e6097131d5f385898c7f0635c0f392b9d0fa165063c8ac"
dependencies = [
"bitflags 2.6.0",
"cfg-if",
@@ -707,9 +707,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.15.0"
+version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
+checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
[[package]]
name = "heck"
@@ -800,13 +800,13 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "jailer"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
dependencies = [
"libc",
"log-instrument",
"nix 0.29.0",
"regex",
- "thiserror",
+ "thiserror 2.0.3",
"utils",
"vmm-sys-util",
]
@@ -822,9 +822,9 @@ dependencies = [
[[package]]
name = "kvm-bindings"
-version = "0.9.1"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2efe3f1a4437bffe000e6297a593b98184213cd27486776c335f95ab53d48e3a"
+checksum = "fa4933174d0cc4b77b958578cd45784071cc5ae212c2d78fbd755aaaa6dfa71a"
dependencies = [
"serde",
"vmm-sys-util",
@@ -833,9 +833,9 @@ dependencies = [
[[package]]
name = "kvm-ioctls"
-version = "0.18.0"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92c2176b91f68903b54ac8c6185bada7d607ca6110998976ff15c032f88a7d39"
+checksum = "337d1afa126368bbd6a5c328048f71a69a737e9afe7e436b392a8f8d770c9171"
dependencies = [
"bitflags 2.6.0",
"kvm-bindings",
@@ -857,9 +857,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.161"
+version = "0.2.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
+checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
[[package]]
name = "libloading"
@@ -873,15 +873,15 @@ dependencies = [
[[package]]
name = "libm"
-version = "0.2.8"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
+checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
[[package]]
name = "linux-loader"
-version = "0.12.0"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d379d0089d0fbf4161c35a4fdfd76125923f1a93632c49195f5372b4c0b1472"
+checksum = "870c3814345f050991f99869417779f6062542bcf4ed81db7a1b926ad1306638"
dependencies = [
"vm-memory",
]
@@ -1057,9 +1057,9 @@ dependencies = [
[[package]]
name = "prettyplease"
-version = "0.2.24"
+version = "0.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "910d41a655dac3b764f1ade94821093d3610248694320cd072303a8eedcf221d"
+checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
dependencies = [
"proc-macro2",
"syn",
@@ -1067,9 +1067,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.88"
+version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9"
+checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
@@ -1140,21 +1140,21 @@ dependencies = [
[[package]]
name = "rebase-snap"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
dependencies = [
"displaydoc",
"libc",
"log-instrument",
- "thiserror",
+ "thiserror 2.0.3",
"utils",
"vmm-sys-util",
]
[[package]]
name = "regex"
-version = "1.11.0"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
@@ -1164,9 +1164,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.8"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
@@ -1187,9 +1187,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
-version = "0.38.37"
+version = "0.38.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
+checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0"
dependencies = [
"bitflags 2.6.0",
"errno",
@@ -1215,7 +1215,7 @@ dependencies = [
[[package]]
name = "seccompiler"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
dependencies = [
"bincode",
"displaydoc",
@@ -1223,7 +1223,7 @@ dependencies = [
"log-instrument",
"serde",
"serde_json",
- "thiserror",
+ "thiserror 2.0.3",
"utils",
"vmm-sys-util",
]
@@ -1239,18 +1239,18 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.210"
+version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
+checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.210"
+version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
+checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [
"proc-macro2",
"quote",
@@ -1259,9 +1259,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.132"
+version = "1.0.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
+checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
dependencies = [
"itoa",
"memchr",
@@ -1295,7 +1295,7 @@ dependencies = [
[[package]]
name = "snapshot-editor"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
dependencies = [
"clap",
"clap-num",
@@ -1303,7 +1303,7 @@ dependencies = [
"libc",
"log-instrument",
"semver",
- "thiserror",
+ "thiserror 2.0.3",
"utils",
"vmm",
"vmm-sys-util",
@@ -1323,9 +1323,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
-version = "2.0.82"
+version = "2.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021"
+checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
dependencies = [
"proc-macro2",
"quote",
@@ -1334,18 +1334,38 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.64"
+version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
- "thiserror-impl",
+ "thiserror-impl 1.0.69",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
+dependencies = [
+ "thiserror-impl 2.0.3",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.64"
+version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
+checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
dependencies = [
"proc-macro2",
"quote",
@@ -1455,7 +1475,7 @@ dependencies = [
"cfg-if",
"libc",
"nix 0.27.1",
- "thiserror",
+ "thiserror 1.0.69",
"userfaultfd-sys",
]
@@ -1486,7 +1506,7 @@ dependencies = [
"log-instrument",
"serde",
"serde_json",
- "thiserror",
+ "thiserror 2.0.3",
"vm-memory",
"vmm-sys-util",
]
@@ -1521,9 +1541,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "vhost"
-version = "0.12.0"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c1c4c6c9f79fbe3150d9a403008ca416d34c489897effdda28b646f09900aad"
+checksum = "bce0aad4d8776cb64f1ac591e908a561c50ba6adac4416296efee590b155623f"
dependencies = [
"bitflags 2.6.0",
"libc",
@@ -1539,7 +1559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e4ce718bd4e8d74b1747363e27f715a6b1bd6971597cb21425dadbf4e712241"
dependencies = [
"libc",
- "thiserror",
+ "thiserror 1.0.69",
]
[[package]]
@@ -1550,12 +1570,12 @@ checksum = "7e21282841a059bb62627ce8441c491f09603622cd5a21c43bfedc85a2952f23"
[[package]]
name = "vm-memory"
-version = "0.15.0"
+version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a320fc11792e063174402ff444aa3c80363cbf1e31c47b5ef74124406c334ce6"
+checksum = "f1720e7240cdc739f935456eb77f370d7e9b2a3909204da1e2b47bef1137a013"
dependencies = [
"libc",
- "thiserror",
+ "thiserror 1.0.69",
"winapi",
]
@@ -1600,7 +1620,7 @@ dependencies = [
"serde",
"serde_json",
"slab",
- "thiserror",
+ "thiserror 2.0.3",
"timerfd",
"userfaultfd",
"utils",
@@ -1610,7 +1630,7 @@ dependencies = [
"vm-memory",
"vm-superio",
"vmm-sys-util",
- "zerocopy 0.8.6",
+ "zerocopy 0.8.10",
]
[[package]]
@@ -1787,11 +1807,11 @@ dependencies = [
[[package]]
name = "zerocopy"
-version = "0.8.6"
+version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a65238aacd5fb83fb03fcaf94823e71643e937000ec03c46e7da94234b10c870"
+checksum = "a13a42ed30c63171d820889b2981318736915150575b8d2d6dbee7edd68336ca"
dependencies = [
- "zerocopy-derive 0.8.6",
+ "zerocopy-derive 0.8.10",
]
[[package]]
@@ -1807,9 +1827,9 @@ dependencies = [
[[package]]
name = "zerocopy-derive"
-version = "0.8.6"
+version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ca22c4ad176b37bd81a565f66635bde3d654fe6832730c3e52e1018ae1655ee"
+checksum = "593e7c96176495043fcb9e87cf7659f4d18679b5bab6b92bdef359c76a7795dd"
dependencies = [
"proc-macro2",
"quote",
diff --git a/README.md b/README.md
index dde5c21e794..f98079fc81c 100644
--- a/README.md
+++ b/README.md
@@ -132,7 +132,7 @@ We test all combinations of:
| Instance | Host OS & Kernel | Guest Rootfs | Guest Kernel |
| :-------- | :---------------- | :----------- | :----------- |
-| c5n.metal | al2 linux_5.10 | ubuntu 22.04 | linux_5.10 |
+| c5n.metal | al2 linux_5.10 | ubuntu 24.04 | linux_5.10 |
| m5n.metal | al2023 linux_6.1 | | linux_6.1 |
| m6i.metal | | | |
| m6a.metal | | | |
diff --git a/docs/RELEASE_POLICY.md b/docs/RELEASE_POLICY.md
index 07cfe70c9b7..fe2f881d6b6 100644
--- a/docs/RELEASE_POLICY.md
+++ b/docs/RELEASE_POLICY.md
@@ -90,9 +90,10 @@ v3.1 will be patched since were the last two Firecracker releases and less than
| Release | Release Date | Latest Patch | Min. end of support | Official end of Support |
| ------: | -----------: | -----------: | ------------------: | :------------------------------ |
+| v1.10 | 2024-11-07 | v1.10.1 | 2025-05-07 | Supported |
| v1.9 | 2024-09-02 | v1.9.1 | 2025-03-02 | Supported |
| v1.8 | 2024-07-10 | v1.8.0 | 2025-01-10 | Supported |
-| v1.7 | 2024-03-18 | v1.7.0 | 2024-09-18 | Supported |
+| v1.7 | 2024-03-18 | v1.7.0 | 2024-09-18 | 2024-09-18 (end of 6mo support) |
| v1.6 | 2023-12-20 | v1.6.0 | 2024-06-20 | 2024-07-10 (v1.8 released) |
| v1.5 | 2023-10-09 | v1.5.1 | 2024-04-09 | 2024-04-09 (end of 6mo support) |
| v1.4 | 2023-07-20 | v1.4.1 | 2024-01-20 | 2024-01-20 (end of 6mo support) |
diff --git a/docs/gdb-debugging.md b/docs/gdb-debugging.md
index 74832665c9d..f230dbb0cc6 100644
--- a/docs/gdb-debugging.md
+++ b/docs/gdb-debugging.md
@@ -6,8 +6,6 @@ Firecracker supports debugging the guest kernel via GDB remote serial protocol.
This allows us to connect GDB to the firecracker process and step through debug
the guest kernel.
-The GDB feature requires Firecracker to be booted with a config file.
-
## Prerequisites
Firstly, to enable GDB debugging we need to compile Firecracker with the `gdb`
@@ -25,22 +23,35 @@ debugging to work. The key config options to enable are:
```
CONFIG_FRAME_POINTER=y
-CONFIG_KGDB=y
-CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_DEBUG_INFO=y
```
-For GDB debugging the `gdb-socket` option should be set in your config file. In
-this example we set it to `/tmp/gdb.socket`
+For GDB debugging the `gdb_socket_path` option under `machine-config` should be
+set. When using the API the socket address must be set before instance start.
+
+In this example we set the address to `/tmp/gdb.socket` in the config file:
```
{
...
- "gdb-socket": "/tmp/gdb.socket"
+ "machine-config": {
+ ...
+ "gdb_socket_path": "/tmp/gdb.socket"
+ ...
+ }
...
}
```
+Using the API the socket address can be configured before boot like so:
+
+```
+sudo curl -X PATCH --unix-socket "${API_SOCKET}" \
+ --data "{
+ \"gdb_socket_path\": \"/tmp/gdb.socket\"
+ }" "http://localhost/machine-config"
+```
+
## Starting Firecracker with GDB
With all the prerequisites in place you can now start firecracker ready to
diff --git a/docs/getting-started.md b/docs/getting-started.md
index cb9a7fee9ee..644d31e78a8 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -9,7 +9,7 @@ You can check if your system meets the requirements by running
`firecracker/tools/devtool checkenv`.
An opinionated way to run Firecracker is to launch an
-[EC2](https://aws.amazon.com/ec2/) `c5.metal` instance with Ubuntu 22.04.
+[EC2](https://aws.amazon.com/ec2/) `c5.metal` instance with Ubuntu 24.04.
Firecracker requires [the KVM Linux kernel module](https://www.linux-kvm.org/)
to perform its virtualization and emulation tasks.
@@ -95,24 +95,26 @@ For simplicity, this guide will not use the [`jailer`](../src/jailer/).
To successfully start a microVM, you will need an uncompressed Linux kernel
binary, and an ext4 file system image (to use as rootfs). This guide uses a 5.10
-kernel image with a Ubuntu 22.04 rootfs from our CI:
+kernel image with a Ubuntu 24.04 rootfs from our CI:
```bash
ARCH="$(uname -m)"
-latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.10/x86_64/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep "(?<=)(firecracker-ci/v1.10/x86_64/vmlinux-5\.10\.[0-9]{3})(?=)" -o -P)
+latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.10/$ARCH/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep -oP "(?<=)(firecracker-ci/v1.10/$ARCH/vmlinux-5\.10\.[0-9]{1,3})(?=)")
# Download a linux kernel binary
wget "https://s3.amazonaws.com/spec.ccfc.min/${latest}"
# Download a rootfs
-wget "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-22.04.ext4"
-
-# Download the ssh key for the rootfs
-wget "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-22.04.id_rsa"
-
-# Set user read permission on the ssh key
-chmod 400 ./ubuntu-22.04.id_rsa
+wget -O ubuntu-24.04.squashfs.upstream "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-24.04.squashfs"
+
+# Create an ssh key for the rootfs
+unsquashfs ubuntu-24.04.squashfs.upstream
+ssh-keygen -f id_rsa -N ""
+cp -v id_rsa.pub squashfs-root/root/.ssh/authorized_keys
+mv -v id_rsa ./ubuntu-24.04.id_rsa
+# re-squash
+mksquashfs squashfs-root ubuntu-24.04.squashfs -all-root -noappend -comp zstd
```
### Getting a Firecracker Binary
@@ -238,7 +240,7 @@ sudo curl -X PUT --unix-socket "${API_SOCKET}" \
}" \
"http://localhost/boot-source"
-ROOTFS="./ubuntu-22.04.ext4"
+ROOTFS="./ubuntu-24.04.ext4"
# Set rootfs
sudo curl -X PUT --unix-socket "${API_SOCKET}" \
@@ -280,13 +282,13 @@ sudo curl -X PUT --unix-socket "${API_SOCKET}" \
sleep 2s
# Setup internet access in the guest
-ssh -i ./ubuntu-22.04.id_rsa root@172.16.0.2 "ip route add default via 172.16.0.1 dev eth0"
+ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 "ip route add default via 172.16.0.1 dev eth0"
# Setup DNS resolution in the guest
-ssh -i ./ubuntu-22.04.id_rsa root@172.16.0.2 "echo 'nameserver 8.8.8.8' > /etc/resolv.conf"
+ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 "echo 'nameserver 8.8.8.8' > /etc/resolv.conf"
# SSH into the microVM
-ssh -i ./ubuntu-22.04.id_rsa root@172.16.0.2
+ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2
# Use `root` for both the login and password.
# Run `reboot` to exit.
diff --git a/docs/network-setup.md b/docs/network-setup.md
index ad77bd3e7e9..fb2c1ca0977 100644
--- a/docs/network-setup.md
+++ b/docs/network-setup.md
@@ -1,49 +1,108 @@
# Getting Started Firecracker Network Setup
-This is a very simple quick-start guide to getting a Firecracker guest connected
-to the network. If you're using Firecracker in production, or even want to run
-multiple guests, you'll need to adapt this setup.
+This is a simple quick-start guide to getting one or more Firecracker microVMs
+connected to the Internet via the host. If you run a production setup, you
+should consider modifying this setup to accommodate your specific needs.
-**Note** Currently firecracker supports only TUN/TAP network backend with no
+**Note:** Currently, Firecracker supports only a TUN/TAP network backend with no
multi queue support.
-The simple steps in this guide assume that your internet-facing interface is
-`eth0`, you have nothing else using `tap0` and no other `iptables` rules. Check
-out the *Advanced:* sections if that doesn't work for you.
+The steps in this guide assume `eth0` to be your Internet-facing network
+interface on the host. If `eth0` isn't your main network interface, you should
+change the value to the correct one in the commands below. IPv4 is also assumed
+to be used, so you will need to adapt the instructions accordingly to support
+IPv6.
+
+Each microVM requires a host network interface (like `eth0`) and a Linux `tap`
+device (like `tap0`) used by Firecracker, but the differences in configuration
+stem from routing: how packets from the `tap` get to the network interface
+(egress) and vice-versa (ingress). There are three main approaches of how to
+configure routing for a microVM.
+
+1. **NAT-based**, which is presented in the main part of this guide. It is
+ simple but doesn't expose your microVM to the local network (LAN).
+1. **Bridge-based**, which exposes your microVM to the local network. Learn more
+ about in the _Advanced: Bridge-based routing_ section of this guide.
+1. **Namespaced NAT**, which sacrifices performance in comparison to the other
+ approaches but is desired in the scenario when two clones of the same microVM
+ are running at the same time. To learn more about it, check out the
+ [Network Connectivity for Clones](./snapshotting/network-for-clones.md)
+ guide.
+
+To run multiple microVMs while using NAT-based routing, check out the _Advanced:
+Multiple guests_ section. The same principles can be applied to other routing
+methods with a bit more effort.
+
+For the choice of firewall, `nft` is recommended for use on production Linux
+systems, but, for the sake of compatibility, this guide provides a choice
+between either `nft` or the `iptables-nft` translation layer. The latter is
+[no longer recommended](https://access.redhat.com/solutions/6739041) but may be
+more familiar to readers.
+
+## On the Host
+
+The first step on the host for any microVM is to create a Linux `tap` device,
+which Firecracker will use for networking.
+
+For this setup, only two IP addresses will be necessary - one for the `tap`
+device and one for the guest itself, through which you will, for example, `ssh`
+into the guest. So, we'll choose the smallest IPv4 subnet needed for 2
+addresses: `/30`. For this VM, let's use the `172.16.0.1` `tap` IP and the
+`172.16.0.2` guest IP.
-## On The Host
+```bash
+# Create the tap device.
+sudo ip tuntap add tap0 mode tap
+# Assign it the tap IP and start up the device.
+sudo ip addr add 172.16.0.1/30 dev tap0
+sudo ip link set tap0 up
+```
-The first step on the host is to create a `tap` device:
+**Note:** The IP of the TAP device should be chosen such that it's not in the
+same subnet as the IP address of the host.
+
+We'll need to enable IPv4 forwarding on the system.
```bash
-sudo ip tuntap add tap0 mode tap
+echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
```
-Then you have a few options for routing traffic out of the tap device, through
-your host's network interface. One option is NAT, set up like this:
+### Configuration via `nft`
+
+We'll need an nftables table for our routing needs, and 2 chains inside that
+table: one for NAT on `postrouting` stage, and another one for filtering on
+`forward` stage:
```bash
-sudo ip addr add 172.16.0.1/24 dev tap0
-sudo ip link set tap0 up
-sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
-sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
-sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-sudo iptables -A FORWARD -i tap0 -o eth0 -j ACCEPT
+sudo nft add table firecracker
+sudo nft 'add chain firecracker postrouting { type nat hook postrouting priority srcnat; policy accept; }'
+sudo nft 'add chain firecracker filter { type filter hook forward priority filter; policy accept; }'
```
-*Note:* The IP of the TAP device should be chosen such that it's not in the same
-subnet as the IP address of the host.
+The first rule we'll need will masquerade packets from the guest IP as if they
+came from the host's IP, by changing the source IP address of these packets:
-*Advanced:* If you are running multiple Firecracker MicroVMs in parallel, or
-have something else on your system using `tap0` then you need to create a `tap`
-for each one, with a unique name.
+```bash
+sudo nft add rule firecracker postrouting ip saddr 172.16.0.2 oifname eth0 counter masquerade
+```
-*Advanced:* You also need to do the `iptables` set up for each new `tap`. If you
-have `iptables` rules you care about on your host, you may want to save those
-rules before starting.
+The second rule we'll need will accept packets from the tap IP (the guest will
+use the tap IP as its gateway and will therefore route its own packets through
+the tap IP) and direct them to the host network interface:
```bash
-sudo iptables-save > iptables.rules.old
+sudo nft add rule firecracker filter iifname tap0 oifname eth0 accept
+```
+
+### Configuration via `iptables-nft`
+
+Tables and chains are managed by `iptables-nft` automatically, but we'll need
+three rules to perform the NAT steps:
+
+```bash
+sudo iptables-nft -t nat -A POSTROUTING -o eth0 -s 172.16.0.2 -j MASQUERADE
+sudo iptables-nft -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+sudo iptables-nft -A FORWARD -i tap0 -o eth0 -j ACCEPT
```
## Setting Up Firecracker
@@ -85,14 +144,20 @@ configuration file like this:
```
Alternatively, if you are using firectl, add
---tap-device=tap0/06:00:AC:10:00:02\` to your command line.
+`--tap-device=tap0/06:00:AC:10:00:02\` to your command line.
## In The Guest
-Once you have booted the guest, bring up networking within the guest:
+Once you have booted the guest, it will have its networking interface with the
+name specified by `iface_id` in the Firecracker configuration.
+
+You'll now need to assign the guest its IP, activate the guest's networking
+interface and set up the `tap` IP as the guest's gateway address, so that
+packets are routed through the `tap` device, where they are then picked up by
+the setup on the host prepared before:
```bash
-ip addr add 172.16.0.2/24 dev eth0
+ip addr add 172.16.0.2/30 dev eth0
ip link set eth0 up
ip route add default via 172.16.0.1 dev eth0
```
@@ -107,23 +172,183 @@ your environment. For testing, you can add a public DNS server to
nameserver 8.8.8.8
```
-## \[Advanced\] Setting Up a Bridge Interface
+**Note:** Sometimes, it's undesirable to have `iproute2` (providing the `ip`
+command) installed on your guest OS, or you simply want to have these steps be
+performed automatically. To do this, check out the _Advanced: Guest network
+configuration using kernel command line_ section.
+
+## Cleaning up
+
+The first step to cleaning up is to delete the tap device on the host:
+
+```bash
+sudo ip link del tap0
+```
+
+### Cleanup using `nft`
+
+You'll want to delete the two nftables rules for NAT routing from the
+`postrouting` and `filter` chains. To do this with nftables, you'll need to look
+up the _handles_ (identifiers) of these rules by running:
+
+```bash
+sudo nft -a list ruleset
+```
+
+Now, find the `# handle` comments relating to the two rules and delete them. For
+example, if the handle to the masquerade rule is 1 and the one to the forwarding
+rule is 2:
+
+```bash
+sudo nft delete rule firecracker postrouting handle 1
+sudo nft delete rule firecracker filter handle 2
+```
+
+Run the following steps only **if you have no more guests** running on the host:
+
+Set IPv4 forwarding back to disabled:
+
+```bash
+echo 0 | sudo tee /proc/sys/net/ipv4/ip_forward
+```
+
+If you're using `nft`, delete the `firecracker` table to revert your nftables
+configuration fully back to its initial state:
+
+```bash
+sudo nft delete table firecracker
+```
+
+### Cleanup using `iptables-nft`
+
+Of the configured `iptables-nft` rules, two should be deleted if you have guests
+remaining in your configuration:
+
+```bash
+sudo iptables-nft -t nat -D POSTROUTING -o eth0 -s 172.16.0.2 -j MASQUERADE
+sudo iptables-nft -D FORWARD -i tap0 -o eth0 -j ACCEPT
+```
+
+**If you have no more guests** running on the host, then similarly set IPv4
+forwarding back to disabled:
+
+```bash
+echo 0 | sudo tee /proc/sys/net/ipv4/ip_forward
+```
+
+And delete the remaining `conntrack` rule that applies to all guests:
+
+```bash
+sudo iptables-nft -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+```
+
+If nothing else is using `iptables-nft` on the system, you may even want to
+delete the entire system ruleset like so:
+
+```bash
+sudo iptables-nft -F
+sudo iptables-nft -t nat -F
+```
+
+## Advanced: Multiple guests
+
+To configure multiple guests, we will only need to repeat some of the steps in
+this setup for each of the microVMs:
+
+1. Each microVM has its own subnet and the two IP addresses inside of it: the
+ `tap` IP and the guest IP.
+1. Each microVM has its own two nftables rules for masquerading and forwarding,
+ while the same table and two chains can be shared between the microVMs.
+1. Each microVM has its own routing configuration inside the guest itself
+ (achieved through `iproute2` or the method described in the _Advanced: Guest
+ network configuration at kernel level_ section).
+
+To give a more concrete example, **let's add a second microVM** to the one
+you've already configured:
+
+Let's assume we allocate /30 subnets in the 172.16.0.0/16 range sequentially to
+give out as few addresses as needed.
+
+The next /30 subnet in the 172.16.0.0/16 range will give us these two IPs:
+172.16.0.5 as the `tap` IP and 172.16.0.6 as the guest IP.
+
+Our new `tap` device will, sequentially, have the name `tap1`:
+
+```bash
+sudo ip tuntap add tap1 mode tap
+sudo ip addr add 172.16.0.5/30 dev tap1
+sudo ip link set tap1 up
+```
+
+Now, let's add the new two `nft` rules, also with the new values:
+
+```bash
+sudo nft add rule firecracker postrouting ip saddr 172.16.0.6 oifname eth0 counter masquerade
+sudo nft add rule firecracker filter iifname tap1 oifname eth0 accept
+```
+
+If using `iptables-nft`, add the rules like so:
+
+```bash
+sudo iptables-nft -t nat -A POSTROUTING -o eth0 -s 172.16.0.6 -j MASQUERADE
+sudo iptables-nft -A FORWARD -i tap1 -o eth0 -j ACCEPT
+```
+
+Modify your Firecracker configuration with the `host_dev_name` now being `tap1`
+instead of `tap0`, boot up the guest and perform the routing inside of it like
+so, changing the guest IP and `tap` IP:
+
+```bash
+ip addr add 172.16.0.6/30 dev eth0
+ip link set eth0 up
+ip route add default via 172.16.0.5 dev eth0
+```
+
+Or, you can use the setup from _Advanced: Guest network configuration at kernel
+level_ by simply changing the G and T variables, i.e. the guest IP and `tap` IP.
+
+**Note:** if you'd like to calculate the guest and `tap` IPs using the
+sequential subnet allocation method that has been used here, you can use the
+following formulas specific to IPv4 addresses:
+
+`tap` IP = `172.16.[(A*O+1)/256].[(A*O+1)%256]`.
+
+Guest IP = `172.16.[(A*O+2)/256].[(A*O+2)%256]`.
+
+Round down the division and replace `A` with the amount of IP addresses inside
+your subnet (for a /30 subnet, that will be 4 addresses, for example) and
+replace `O` with the sequential number of your microVM, starting at 0. You can
+replace `172.16` with any other values that fit between between 1 and 255 as
+usual with an IPv4 address.
+
+For example, let's calculate the addresses of the 1000-th microVM with a /30
+subnet in the `172.16.0.0/16` range:
+
+`tap` IP = `172.16.[(4*999+1)/256].[(4*999+1)%256]` = `172.16.15.157`.
+
+Guest IP = `172.16.[(4*999+2)/256].[(4*999+2)%256]` = `172.16.15.158`.
+
+This allocation setup has been used successfully in the `firecracker-demo`
+project for launching several thousand microVMs on the same host:
+[relevant lines](https://github.com/firecracker-microvm/firecracker-demo/blob/63717c6e7fbd277bdec8e26a5533d53544a760bb/start-firecracker.sh#L45).
+
+## Advanced: Bridge-based routing
### On The Host
-1. Create a bridge interface
+1. Create a bridge interface:
```bash
sudo ip link add name br0 type bridge
```
-1. Add tap interface [created above](#on-the-host) to the bridge
+1. Add the `tap` device [created above](#on-the-host) to the bridge:
```bash
sudo ip link set dev tap0 master br0
```
-1. Define an IP address in your network for the bridge.
+1. Define an IP address in your network for the bridge:
For example, if your gateway were on `192.168.1.1` and you wanted to use this
for getting dynamic IPs, you would want to give the bridge an unused IP
@@ -133,24 +358,30 @@ nameserver 8.8.8.8
sudo ip address add 192.168.1.7/24 dev br0
```
-1. Add firewall rules to allow traffic to be routed to the guest
+1. Add a firewall rule to allow traffic to be routed to the guest:
```bash
sudo iptables -t nat -A POSTROUTING -o br0 -j MASQUERADE
```
+1. Once you're cleaning up the configuration, make sure to delete the bridge:
+
+ ```bash
+ sudo ip link del br0
+ ```
+
### On The Guest
1. Define an unused IP address in the bridge's subnet e.g., `192.168.1.169/24`.
- _Note: Alternatively, you could rely on DHCP for getting a dynamic IP address
- from your gateway._
+ **Note**: Alternatively, you could rely on DHCP for getting a dynamic IP
+ address from your gateway.
```bash
ip addr add 192.168.1.169/24 dev eth0
```
-1. Set the interface up.
+1. Enable the network interface:
```bash
ip link set eth0 up
@@ -177,43 +408,38 @@ nameserver 8.8.8.8
192.168.1.1 via 192.168.1.7 dev eth0
```
-1. Add your nameserver to `resolve.conf`
+1. Add your nameserver to `/etc/resolve.conf`
```bash
# cat /etc/resolv.conf
nameserver 192.168.1.1
```
-## Cleaning up
+## Advanced: Guest network configuration using kernel command line
-The first step to cleaning up is deleting the tap device:
+The Linux kernel supports an `ip` CLI arguments that can be passed to it when
+booting. Boot arguments in Firecracker are configured in the `boot_args`
+property of the boot source (`boot-source` object in the JSON configuration or
+the equivalent endpoint in the API server).
-```bash
-sudo ip link del tap0
-```
+The value of the `ip` CLI argument for our setup will be the of this format:
+`G::T:GM::GI:off`. G is the guest IP (without the subnet), T is the `tap` IP
+(without the subnet), GM is the "long" mask IP of the guest CIDR and GI is the
+name of the guest network interface.
-If you don't have anything else using `iptables` on your machine, clean up those
-rules:
-
-```bash
-sudo iptables -F
-sudo sh -c "echo 0 > /proc/sys/net/ipv4/ip_forward" # usually the default
-```
+Substituting our values, we get:
+`ip=172.16.0.2::172.16.0.1:255.255.255.252::eth0:off`. Insert this at the end of
+your boot arguments for your microVM, and the guest Linux kernel will
+automatically perform the routing configuration done in the _In the Guest_
+section without needing `iproute2` installed in the guest.
-If you have an existing iptables setup, you'll want to be more careful about
-cleaning up.
+As soon as you boot the guest, it will already be connected to the network
+(assuming you correctly performing the other steps).
-*Advanced:* If you saved your iptables rules in the first step, then you can
-restore them like this:
+**Note**: you can also use the `ip` argument to configure a primary DNS server
+and, optionally, a second DNS server without needing to touch
+`/etc/resolv.conf`. As an example:
-```bash
-if [ -f iptables.rules.old ]; then
- sudo iptables-restore < iptables.rules.old
-fi
-```
-
-*Advanced:* If you created a bridge interface, delete it using the following:
-
-```bash
-sudo ip link del br0
-```
+`ip=172.16.0.2::172.16.0.1:255.255.255.252::eth0:off:8.8.8.8:1.1.1.1` configures
+`8.8.8.8` as the primary DNS server and `1.1.1.1` as the secondary DNS server,
+as well as the rest of the guest-side routing.
diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md
index a9e0bc8dc4c..75ffd306e25 100644
--- a/docs/snapshotting/snapshot-support.md
+++ b/docs/snapshotting/snapshot-support.md
@@ -642,8 +642,8 @@ booting, to avoid this issue.
We have a mechanism in place to experiment with snapshot compatibility across
supported host kernel versions by generating snapshot artifacts through
-[this tool](../../tools/create_snapshot_artifact) and checking devices'
-functionality using
+[this test](../../tests/integration_tests/functional/test_snapshot_phase1.py)
+and checking devices' functionality using
[this test](../../tests/integration_tests/functional/test_snapshot_restore_cross_kernel.py).
The test restores the snapshot and ensures that all the devices set-up (network
devices, disk, vsock, balloon and MMDS) are operational post-load.
diff --git a/resources/guest_configs/ci.config b/resources/guest_configs/ci.config
new file mode 100644
index 00000000000..7bbf1fb1f56
--- /dev/null
+++ b/resources/guest_configs/ci.config
@@ -0,0 +1,7 @@
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_SQUASHFS_ZSTD=y
+# aarch64 only TBD split into a separate file
+CONFIG_DEVMEM=y
+# CONFIG_ARM64_ERRATUM_3194386 is not set
diff --git a/resources/guest_configs/debug.config b/resources/guest_configs/debug.config
new file mode 100644
index 00000000000..6ff73f2162b
--- /dev/null
+++ b/resources/guest_configs/debug.config
@@ -0,0 +1,5 @@
+CONFIG_FRAME_POINTER=y
+# CONFIG_KGDB=y
+# CONFIG_KGDB_SERIAL_CONSOLE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
diff --git a/resources/guest_configs/ftrace.config b/resources/guest_configs/ftrace.config
new file mode 100644
index 00000000000..b180c7f232a
--- /dev/null
+++ b/resources/guest_configs/ftrace.config
@@ -0,0 +1,11 @@
+CONFIG_FTRACE=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_FUNCTION_GRAPH_TRACER=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_SCHED_TRACER=y
+CONFIG_STACK_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_FTRACE_MCOUNT_RECORD=y
+CONFIG_FTRACE_SYSCALLS=y
diff --git a/resources/guest_configs/patches/0001-fix-Adjust-config-options-for-what-is-needed-by-our-.patch b/resources/guest_configs/patches/0001-fix-Adjust-config-options-for-what-is-needed-by-our-.patch
deleted file mode 100644
index ed1f683dce1..00000000000
--- a/resources/guest_configs/patches/0001-fix-Adjust-config-options-for-what-is-needed-by-our-.patch
+++ /dev/null
@@ -1,98 +0,0 @@
-From 85e406b23c086c446ccfd6f8c83670800cc4de3a Mon Sep 17 00:00:00 2001
-From: Patrick Roy
-Date: Tue, 30 Jul 2024 13:59:04 +0100
-Subject: [PATCH] fix: Adjust config options for what is needed by our tests
-
-Additionally, set `CONFIG_MSDOS_PARTITION=y` for our PARTUUID tests,
-`CONFIG_DEVMEM=y` on aarch64/5.10 (for various integration tests that
-rely on /dev/mem), and CONFIG_IKCONFIG=y and CONFIG_IKCONFIG_PROC=y for
-the spectre-meltdown-checker.sh tests to work on AMD.
-
-Signed-off-by: Patrick Roy
----
- .../guest_configs/microvm-kernel-ci-aarch64-5.10.config | 7 ++++---
- .../microvm-kernel-ci-x86_64-5.10-no-acpi.config | 5 +++--
- .../guest_configs/microvm-kernel-ci-x86_64-5.10.config | 5 +++--
- 3 files changed, 10 insertions(+), 7 deletions(-)
-
-diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config
-index ac44904c..0555055c 100644
---- a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config
-+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config
-@@ -110,7 +110,8 @@ CONFIG_RCU_STALL_COMMON=y
- CONFIG_RCU_NEED_SEGCBLIST=y
- # end of RCU Subsystem
-
--# CONFIG_IKCONFIG is not set
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
- # CONFIG_IKHEADERS is not set
- CONFIG_LOG_BUF_SHIFT=17
- CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
-@@ -752,7 +753,7 @@ CONFIG_PARTITION_ADVANCED=y
- # CONFIG_AMIGA_PARTITION is not set
- # CONFIG_ATARI_PARTITION is not set
- # CONFIG_MAC_PARTITION is not set
--# CONFIG_MSDOS_PARTITION is not set
-+CONFIG_MSDOS_PARTITION=y
- # CONFIG_LDM_PARTITION is not set
- # CONFIG_SGI_PARTITION is not set
- # CONFIG_ULTRIX_PARTITION is not set
-@@ -1726,7 +1727,7 @@ CONFIG_HW_RANDOM_VIRTIO=y
- # CONFIG_HW_RANDOM_CCTRNG is not set
- # CONFIG_HW_RANDOM_XIPHERA is not set
- # CONFIG_HW_RANDOM_GRAVITON is not set
--# CONFIG_DEVMEM is not set
-+CONFIG_DEVMEM=y
- # CONFIG_RAW_DRIVER is not set
- # CONFIG_TCG_TPM is not set
- # CONFIG_XILLYBUS is not set
-diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config
-index b87fb3e4..a27c1f84 100644
---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config
-+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config
-@@ -134,7 +134,8 @@ CONFIG_RCU_NEED_SEGCBLIST=y
- # end of RCU Subsystem
-
- CONFIG_BUILD_BIN2C=y
--# CONFIG_IKCONFIG is not set
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
- # CONFIG_IKHEADERS is not set
- CONFIG_LOG_BUF_SHIFT=17
- CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
-@@ -702,7 +703,7 @@ CONFIG_PARTITION_ADVANCED=y
- # CONFIG_AMIGA_PARTITION is not set
- # CONFIG_ATARI_PARTITION is not set
- # CONFIG_MAC_PARTITION is not set
--# CONFIG_MSDOS_PARTITION is not set
-+CONFIG_MSDOS_PARTITION=y
- # CONFIG_LDM_PARTITION is not set
- # CONFIG_SGI_PARTITION is not set
- # CONFIG_ULTRIX_PARTITION is not set
-diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config
-index 09461c17..af9ec662 100644
---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config
-+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config
-@@ -127,7 +127,8 @@ CONFIG_RCU_NEED_SEGCBLIST=y
- # end of RCU Subsystem
-
- CONFIG_BUILD_BIN2C=y
--# CONFIG_IKCONFIG is not set
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
- # CONFIG_IKHEADERS is not set
- CONFIG_LOG_BUF_SHIFT=17
- CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
-@@ -739,7 +740,7 @@ CONFIG_PARTITION_ADVANCED=y
- # CONFIG_AMIGA_PARTITION is not set
- # CONFIG_ATARI_PARTITION is not set
- # CONFIG_MAC_PARTITION is not set
--# CONFIG_MSDOS_PARTITION is not set
-+CONFIG_MSDOS_PARTITION=y
- # CONFIG_LDM_PARTITION is not set
- # CONFIG_SGI_PARTITION is not set
- # CONFIG_ULTRIX_PARTITION is not set
---
-2.34.1
-
diff --git a/resources/guest_configs/patches/0002-ci-adjust-6.1-guest-kernel-configs-for-our-CI.patch b/resources/guest_configs/patches/0002-ci-adjust-6.1-guest-kernel-configs-for-our-CI.patch
deleted file mode 100644
index 06604fd104a..00000000000
--- a/resources/guest_configs/patches/0002-ci-adjust-6.1-guest-kernel-configs-for-our-CI.patch
+++ /dev/null
@@ -1,76 +0,0 @@
-From 911b916fdc53acfc7229302b029fd615f1e670cf Mon Sep 17 00:00:00 2001
-From: Babis Chalios
-Date: Fri, 23 Aug 2024 12:54:26 +0200
-Subject: [PATCH 2/2] ci: adjust 6.1 guest kernel configs for our CI
-
-Set CONFIG_MSDOS_PARTITION=y for our PARTUUID tests,
-CONFIG_DEVMEM=y on aarch64 for various integration tests that rely on
-/dev/mem being there and CONFIG_IKCONFIG=y, CONFIG_IKCONFIG_PROC=y for
-the spectre-meltdown-checker.sh tests to work on AMD.
-
-Signed-off-by: Babis Chalios
----
- .../guest_configs/microvm-kernel-ci-aarch64-6.1.config | 7 ++++---
- .../guest_configs/microvm-kernel-ci-x86_64-6.1.config | 7 ++++---
- 2 files changed, 8 insertions(+), 6 deletions(-)
-
-diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config
-index 26b87a65..5c0334f4 100644
---- a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config
-+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config
-@@ -140,7 +140,8 @@ CONFIG_RCU_STALL_COMMON=y
- CONFIG_RCU_NEED_SEGCBLIST=y
- # end of RCU Subsystem
-
--# CONFIG_IKCONFIG is not set
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
- # CONFIG_IKHEADERS is not set
- CONFIG_LOG_BUF_SHIFT=17
- CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
-@@ -753,7 +754,7 @@ CONFIG_PARTITION_ADVANCED=y
- # CONFIG_AMIGA_PARTITION is not set
- # CONFIG_ATARI_PARTITION is not set
- # CONFIG_MAC_PARTITION is not set
--# CONFIG_MSDOS_PARTITION is not set
-+CONFIG_MSDOS_PARTITION=y
- # CONFIG_LDM_PARTITION is not set
- # CONFIG_SGI_PARTITION is not set
- # CONFIG_ULTRIX_PARTITION is not set
-@@ -1823,7 +1824,7 @@ CONFIG_HW_RANDOM_VIRTIO=y
- # CONFIG_HW_RANDOM_XIPHERA is not set
- CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=y
- # CONFIG_HW_RANDOM_GRAVITON is not set
--# CONFIG_DEVMEM is not set
-+CONFIG_DEVMEM=y
- # CONFIG_TCG_TPM is not set
- # CONFIG_XILLYBUS is not set
- CONFIG_RANDOM_TRUST_CPU=y
-diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config
-index 967e3203..8a2769c0 100644
---- a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config
-+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config
-@@ -162,8 +162,9 @@ CONFIG_RCU_STALL_COMMON=y
- CONFIG_RCU_NEED_SEGCBLIST=y
- # end of RCU Subsystem
-
--# CONFIG_IKCONFIG is not set
--# CONFIG_IKHEADERS is not set
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
-+# CONFIG_IKHEADERS=y
- CONFIG_LOG_BUF_SHIFT=17
- CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
- CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
-@@ -769,7 +770,7 @@ CONFIG_PARTITION_ADVANCED=y
- # CONFIG_AMIGA_PARTITION is not set
- # CONFIG_ATARI_PARTITION is not set
- # CONFIG_MAC_PARTITION is not set
--# CONFIG_MSDOS_PARTITION is not set
-+CONFIG_MSDOS_PARTITION=y
- # CONFIG_LDM_PARTITION is not set
- # CONFIG_SGI_PARTITION is not set
- # CONFIG_ULTRIX_PARTITION is not set
---
-2.34.1
-
diff --git a/resources/guest_configs/patches/0003-enable-ftrace.patch b/resources/guest_configs/patches/0003-enable-ftrace.patch
deleted file mode 100644
index a836a6fb3a7..00000000000
--- a/resources/guest_configs/patches/0003-enable-ftrace.patch
+++ /dev/null
@@ -1,115 +0,0 @@
-diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config
-index ac44904c1..2a6f2310f 100644
---- a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config
-+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config
-@@ -3089,7 +3089,17 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
- CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
- CONFIG_HAVE_C_RECORDMCOUNT=y
- CONFIG_TRACING_SUPPORT=y
--# CONFIG_FTRACE is not set
-+CONFIG_FTRACE=y
-+CONFIG_FUNCTION_TRACER=y
-+CONFIG_FUNCTION_GRAPH_TRACER=y
-+CONFIG_IRQSOFF_TRACER=y
-+CONFIG_PREEMPT_TRACER=y
-+CONFIG_SCHED_TRACER=y
-+CONFIG_STACK_TRACER=y
-+CONFIG_BLK_DEV_IO_TRACE=y
-+CONFIG_FUNCTION_PROFILER=y
-+CONFIG_FTRACE_MCOUNT_RECORD=y
-+CONFIG_FTRACE_SYSCALLS=y
- # CONFIG_SAMPLES is not set
- CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
- # CONFIG_STRICT_DEVMEM is not set
-diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config
-index 26b87a658..f0f765298 100644
---- a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config
-+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config
-@@ -3309,7 +3309,17 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
- CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
- CONFIG_HAVE_C_RECORDMCOUNT=y
- CONFIG_TRACING_SUPPORT=y
--# CONFIG_FTRACE is not set
-+CONFIG_FTRACE=y
-+CONFIG_FUNCTION_TRACER=y
-+CONFIG_FUNCTION_GRAPH_TRACER=y
-+CONFIG_IRQSOFF_TRACER=y
-+CONFIG_PREEMPT_TRACER=y
-+CONFIG_SCHED_TRACER=y
-+CONFIG_STACK_TRACER=y
-+CONFIG_BLK_DEV_IO_TRACE=y
-+CONFIG_FUNCTION_PROFILER=y
-+CONFIG_FTRACE_MCOUNT_RECORD=y
-+CONFIG_FTRACE_SYSCALLS=y
- # CONFIG_SAMPLES is not set
- # CONFIG_STRICT_DEVMEM is not set
-
-diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config
-index b87fb3e44..fc45dda19 100644
---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config
-+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config
-@@ -2905,7 +2905,17 @@ CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
- CONFIG_HAVE_FENTRY=y
- CONFIG_HAVE_C_RECORDMCOUNT=y
- CONFIG_TRACING_SUPPORT=y
--# CONFIG_FTRACE is not set
-+CONFIG_FTRACE=y
-+CONFIG_FUNCTION_TRACER=y
-+CONFIG_FUNCTION_GRAPH_TRACER=y
-+CONFIG_IRQSOFF_TRACER=y
-+CONFIG_PREEMPT_TRACER=y
-+CONFIG_SCHED_TRACER=y
-+CONFIG_STACK_TRACER=y
-+CONFIG_BLK_DEV_IO_TRACE=y
-+CONFIG_FUNCTION_PROFILER=y
-+CONFIG_FTRACE_MCOUNT_RECORD=y
-+CONFIG_FTRACE_SYSCALLS=y
- # CONFIG_SAMPLES is not set
- CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
- CONFIG_STRICT_DEVMEM=y
-diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config
-index 09461c178..6d85bce2c 100644
---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config
-+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config
-@@ -2987,7 +2987,17 @@ CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
- CONFIG_HAVE_FENTRY=y
- CONFIG_HAVE_C_RECORDMCOUNT=y
- CONFIG_TRACING_SUPPORT=y
--# CONFIG_FTRACE is not set
-+CONFIG_FTRACE=y
-+CONFIG_FUNCTION_TRACER=y
-+CONFIG_FUNCTION_GRAPH_TRACER=y
-+CONFIG_IRQSOFF_TRACER=y
-+CONFIG_PREEMPT_TRACER=y
-+CONFIG_SCHED_TRACER=y
-+CONFIG_STACK_TRACER=y
-+CONFIG_BLK_DEV_IO_TRACE=y
-+CONFIG_FUNCTION_PROFILER=y
-+CONFIG_FTRACE_MCOUNT_RECORD=y
-+CONFIG_FTRACE_SYSCALLS=y
- # CONFIG_SAMPLES is not set
- CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
- CONFIG_STRICT_DEVMEM=y
-diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config
-index 967e32031..d11ef968a 100644
---- a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config
-+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config
-@@ -3185,7 +3185,17 @@ CONFIG_HAVE_OBJTOOL_MCOUNT=y
- CONFIG_HAVE_C_RECORDMCOUNT=y
- CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y
- CONFIG_TRACING_SUPPORT=y
--# CONFIG_FTRACE is not set
-+CONFIG_FTRACE=y
-+CONFIG_FUNCTION_TRACER=y
-+CONFIG_FUNCTION_GRAPH_TRACER=y
-+CONFIG_IRQSOFF_TRACER=y
-+CONFIG_PREEMPT_TRACER=y
-+CONFIG_SCHED_TRACER=y
-+CONFIG_STACK_TRACER=y
-+CONFIG_BLK_DEV_IO_TRACE=y
-+CONFIG_FUNCTION_PROFILER=y
-+CONFIG_FTRACE_MCOUNT_RECORD=y
-+CONFIG_FTRACE_SYSCALLS=y
- # CONFIG_SAMPLES is not set
- CONFIG_HAVE_SAMPLE_FTRACE_DIRECT=y
- CONFIG_HAVE_SAMPLE_FTRACE_DIRECT_MULTI=y
diff --git a/resources/guest_configs/patches/0004-disable-CONFIG_ARM64_ERRATUM_3194386-for-aarch64.patch b/resources/guest_configs/patches/0004-disable-CONFIG_ARM64_ERRATUM_3194386-for-aarch64.patch
deleted file mode 100644
index f3f16925e41..00000000000
--- a/resources/guest_configs/patches/0004-disable-CONFIG_ARM64_ERRATUM_3194386-for-aarch64.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config
-index ac44904c1..9f912a70b 100644
---- a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config
-+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config
-@@ -341,6 +341,7 @@ CONFIG_ARM64_ERRATUM_1463225=y
- CONFIG_ARM64_ERRATUM_1542419=y
- CONFIG_ARM64_ERRATUM_1508412=y
- CONFIG_ARM64_ERRATUM_2457168=y
-+# CONFIG_ARM64_ERRATUM_3194386 is not set
- CONFIG_CAVIUM_ERRATUM_22375=y
- CONFIG_CAVIUM_ERRATUM_23144=y
- CONFIG_CAVIUM_ERRATUM_23154=y
-diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config
-index 26b87a658..29fe130f2 100644
---- a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config
-+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config
-@@ -362,6 +362,7 @@ CONFIG_ARM64_ERRATUM_2441009=y
- CONFIG_ARM64_ERRATUM_2457168=y
- CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD=y
- CONFIG_ARM64_ERRATUM_2966298=y
-+# CONFIG_ARM64_ERRATUM_3194386 is not set
- CONFIG_CAVIUM_ERRATUM_22375=y
- CONFIG_CAVIUM_ERRATUM_23144=y
- CONFIG_CAVIUM_ERRATUM_23154=y
diff --git a/resources/rebuild.sh b/resources/rebuild.sh
index 9f6850d0555..90bac7addb7 100755
--- a/resources/rebuild.sh
+++ b/resources/rebuild.sh
@@ -20,25 +20,6 @@ function install_dependencies {
apt install -y bc flex bison gcc make libelf-dev libssl-dev squashfs-tools busybox-static tree cpio curl patch docker.io
}
-function dir2ext4img {
- # ext4
- # https://unix.stackexchange.com/questions/503211/how-can-an-image-file-be-created-for-a-directory
- local DIR=$1
- local IMG=$2
- # Default size for the resulting rootfs image is 300M
- local SIZE=${3:-300M}
- local TMP_MNT=$(mktemp -d)
- truncate -s "$SIZE" "$IMG"
- mkfs.ext4 -F "$IMG"
- mount "$IMG" "$TMP_MNT"
- tar c -C $DIR . |tar x -C "$TMP_MNT"
- # cleanup
- # Use the -l flag for lazy unmounting since sometimes umount fails
- # with "device busy" and simply calling `sync` doesn't help
- umount -l "$TMP_MNT"
- rmdir $TMP_MNT
-}
-
function prepare_docker {
nohup /usr/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 &
@@ -67,7 +48,7 @@ function build_rootfs {
cp -rvf overlay/* $rootfs
- # curl -O https://cloud-images.ubuntu.com/minimal/releases/jammy/release/ubuntu-22.04-minimal-cloudimg-amd64-root.tar.xz
+ # curl -O https://cloud-images.ubuntu.com/minimal/releases/noble/release/ubuntu-24.04-minimal-cloudimg-amd64-root.tar.xz
#
# TBD use systemd-nspawn instead of Docker
# sudo tar xaf ubuntu-22.04-minimal-cloudimg-amd64-root.tar.xz -C $rootfs
@@ -89,26 +70,13 @@ EOF
# TBD what abt /etc/hosts?
echo | tee $rootfs/etc/resolv.conf
- # Generate key for ssh access from host
- if [ ! -s id_rsa ]; then
- ssh-keygen -f id_rsa -N ""
- fi
- install -d -m 0600 "$rootfs/root/.ssh/"
- cp id_rsa.pub "$rootfs/root/.ssh/authorized_keys"
- id_rsa=$OUTPUT_DIR/$ROOTFS_NAME.id_rsa
- cp id_rsa $id_rsa
-
- # -comp zstd but guest kernel does not support
rootfs_img="$OUTPUT_DIR/$ROOTFS_NAME.squashfs"
mv $rootfs/root/manifest $OUTPUT_DIR/$ROOTFS_NAME.manifest
- mksquashfs $rootfs $rootfs_img -all-root -noappend
- rootfs_ext4=$OUTPUT_DIR/$ROOTFS_NAME.ext4
- dir2ext4img $rootfs $rootfs_ext4
+ mksquashfs $rootfs $rootfs_img -all-root -noappend -comp zstd
rm -rf $rootfs
for bin in fast_page_fault_helper fillmem init readmem; do
rm $PWD/overlay/usr/local/bin/$bin
done
- rm -f id_rsa{,.pub}
rm -f nohup.out
}
@@ -155,12 +123,6 @@ function clone_amazon_linux_repo {
[ -d linux ] || git clone https://github.com/amazonlinux/linux linux
}
-function apply_kernel_patches_for_ci {
- for p in $PWD/guest_configs/patches/* ; do
- patch -p2 < $p
- done
-}
-
# prints the git tag corresponding to the newest and best matching the provided kernel version $1
# this means that if a microvm kernel exists, the tag returned will be of the form
#
@@ -200,8 +162,9 @@ function build_al_kernel {
echo "FATAL: Unsupported architecture!"
exit 1
fi
- cp "$KERNEL_CFG" .config
-
+ # Concatenate all config files into one. olddefconfig will then resolve
+ # as needed. Later values override earlier ones.
+ cat "$@" >.config
make olddefconfig
make -j $(nproc) $target
LATEST_VERSION=$(cat include/config/kernel.release)
@@ -226,16 +189,30 @@ function prepare_and_build_rootfs {
compile_and_install $BIN/devmemread.c $BIN/devmemread
fi
- build_rootfs ubuntu-22.04 jammy
+ build_rootfs ubuntu-24.04 noble
build_initramfs
}
+function vmlinux_split_debuginfo {
+ VMLINUX="$1"
+ DEBUGINFO="$VMLINUX.debug"
+ VMLINUX_ORIG="$VMLINUX"
+ if [ $ARCH = "aarch64" ]; then
+ # in aarch64, the debug info is in vmlinux
+ VMLINUX_ORIG=linux/vmlinux
+ fi
+ objcopy --only-keep-debug $VMLINUX_ORIG $DEBUGINFO
+ objcopy --preserve-dates --strip-debug --add-gnu-debuglink=$DEBUGINFO $VMLINUX
+ # gdb does not support compressed files, but compress them because they are huge
+ gzip -v $DEBUGINFO
+}
+
function build_al_kernels {
if [[ $# = 0 ]]; then
local KERNEL_VERSION="all"
elif [[ $# -ne 1 ]]; then
die "Too many arguments in '$(basename $0) kernels' command. Please use \`$0 help\` for help."
- else
+ else
KERNEL_VERSION=$1
if [[ "$KERNEL_VERSION" != @(5.10|5.10-no-acpi|6.1) ]]; then
die "Unsupported kernel version: '$KERNEL_VERSION'. Please use \`$0 help\` for help."
@@ -244,22 +221,31 @@ function build_al_kernels {
clone_amazon_linux_repo
- # Apply kernel patches on top of AL configuration
- apply_kernel_patches_for_ci
+ CI_CONFIG="$PWD/guest_configs/ci.config"
if [[ "$KERNEL_VERSION" == @(all|5.10) ]]; then
- build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config
+ build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config "$CI_CONFIG"
fi
if [[ $ARCH == "x86_64" && "$KERNEL_VERSION" == @(all|5.10-no-acpi) ]]; then
- build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10-no-acpi.config
+ build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10-no-acpi.config "$CI_CONFIG"
fi
if [[ "$KERNEL_VERSION" == @(all|6.1) ]]; then
- build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config 5.10
+ build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config "$CI_CONFIG"
fi
- # Undo kernel patches on top of AL configuration
- git restore $PWD/guest_configs
- rm -rf $PWD/guest_configs/*.orig
+ # Build debug kernels
+ FTRACE_CONFIG="$PWD/guest_configs/ftrace.config"
+ DEBUG_CONFIG="$PWD/guest_configs/debug.config"
+ OUTPUT_DIR=$OUTPUT_DIR/debug
+ mkdir -pv $OUTPUT_DIR
+ if [[ "$KERNEL_VERSION" == @(all|5.10) ]]; then
+ build_al_kernel "$PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config" "$CI_CONFIG" "$FTRACE_CONFIG" "$DEBUG_CONFIG"
+ vmlinux_split_debuginfo $OUTPUT_DIR/vmlinux-5.10.*
+ fi
+ if [[ "$KERNEL_VERSION" == @(all|6.1) ]]; then
+ build_al_kernel "$PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config" "$CI_CONFIG" "$FTRACE_CONFIG" "$DEBUG_CONFIG"
+ vmlinux_split_debuginfo $OUTPUT_DIR/vmlinux-6.1.*
+ fi
}
function print_help {
@@ -267,25 +253,25 @@ function print_help {
Firecracker CI artifacts build script
Usage: $(basename $0) [] []
-
+
Available commands:
-
+
all (default)
Build CI rootfs and default guest kernels using configurations from
resources/guest_configs.
This will patch the guest configurations with all the patches under
resources/guest_configs/patches.
This is the default command, if no command is chosen.
-
+
rootfs
Builds only the CI rootfs.
-
+
kernels [version]
Builds our the currently supported CI kernels.
-
+
version: Optionally choose a kernel version to build. Supported
versions are: 5.10, 5.10-no-acpi or 6.1.
-
+
help
Displays the help message and exits.
EOF
@@ -310,7 +296,7 @@ function main {
fi
set -x
-
+
install_dependencies
# Create the directory in which we will store the kernels and rootfs
diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml
index a8310913092..15137400180 100644
--- a/src/acpi-tables/Cargo.toml
+++ b/src/acpi-tables/Cargo.toml
@@ -8,9 +8,9 @@ license = "Apache-2.0"
[dependencies]
displaydoc = "0.2.5"
-thiserror = "1.0.64"
-vm-memory = { version = "0.15.0", features = ["backend-mmap", "backend-bitmap"] }
-zerocopy = { version = "0.8.6", features = ["derive"] }
+thiserror = "2.0.3"
+vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] }
+zerocopy = { version = "0.8.10", features = ["derive"] }
[lib]
bench = false
diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml
index 9b49bf6475d..91e03a2afb8 100644
--- a/src/clippy-tracing/Cargo.toml
+++ b/src/clippy-tracing/Cargo.toml
@@ -10,11 +10,11 @@ name = "clippy-tracing"
bench = false
[dependencies]
-clap = { version = "4.5.20", features = ["derive"] }
+clap = { version = "4.5.21", features = ["derive"] }
itertools = "0.13.0"
-proc-macro2 = { version = "1.0.88", features = ["span-locations"] }
+proc-macro2 = { version = "1.0.89", features = ["span-locations"] }
quote = "1.0.37"
-syn = { version = "2.0.82", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] }
+syn = { version = "2.0.85", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] }
walkdir = "2.5.0"
[dev-dependencies]
diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml
index 7e5e5110dfc..6654bb090c4 100644
--- a/src/cpu-template-helper/Cargo.toml
+++ b/src/cpu-template-helper/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "cpu-template-helper"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
authors = ["Amazon Firecracker team "]
edition = "2021"
license = "Apache-2.0"
@@ -10,13 +10,13 @@ name = "cpu-template-helper"
bench = false
[dependencies]
-clap = { version = "4.5.20", features = ["derive", "string"] }
+clap = { version = "4.5.21", features = ["derive", "string"] }
displaydoc = "0.2.5"
-libc = "0.2.161"
+libc = "0.2.164"
log-instrument = { path = "../log-instrument", optional = true }
-serde = { version = "1.0.210", features = ["derive"] }
-serde_json = "1.0.132"
-thiserror = "1.0.64"
+serde = { version = "1.0.215", features = ["derive"] }
+serde_json = "1.0.133"
+thiserror = "2.0.3"
vmm = { path = "../vmm" }
vmm-sys-util = "0.12.1"
diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml
index 231050dbd9f..8d0889c23dd 100644
--- a/src/firecracker/Cargo.toml
+++ b/src/firecracker/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "firecracker"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
authors = ["Amazon Firecracker team "]
edition = "2021"
build = "build.rs"
@@ -18,15 +18,15 @@ bench = false
[dependencies]
displaydoc = "0.2.5"
event-manager = "0.4.0"
-libc = "0.2.161"
+libc = "0.2.164"
log-instrument = { path = "../log-instrument", optional = true }
micro_http = { git = "https://github.com/firecracker-microvm/micro-http" }
seccompiler = { path = "../seccompiler" }
-serde = { version = "1.0.210", features = ["derive"] }
+serde = { version = "1.0.215", features = ["derive"] }
serde_derive = "1.0.136"
-serde_json = "1.0.132"
-thiserror = "1.0.64"
+serde_json = "1.0.133"
+thiserror = "2.0.3"
timerfd = "1.6.0"
utils = { path = "../utils" }
vmm = { path = "../vmm" }
@@ -34,18 +34,18 @@ vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }
[dev-dependencies]
cargo_toml = "0.20.5"
-libc = "0.2.161"
-regex = { version = "1.11.0", default-features = false, features = ["std", "unicode-perl"] }
+libc = "0.2.164"
+regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] }
# Dev-Dependencies for uffd examples
-serde = { version = "1.0.210", features = ["derive"] }
+serde = { version = "1.0.215", features = ["derive"] }
userfaultfd = "0.8.1"
[build-dependencies]
bincode = "1.2.1"
seccompiler = { path = "../seccompiler" }
-serde = { version = "1.0.210" }
-serde_json = "1.0.132"
+serde = { version = "1.0.215" }
+serde_json = "1.0.133"
[features]
tracing = ["log-instrument", "seccompiler/tracing", "utils/tracing", "vmm/tracing"]
diff --git a/src/firecracker/src/api_server/parsed_request.rs b/src/firecracker/src/api_server/parsed_request.rs
index 125463d1d05..10405c156ec 100644
--- a/src/firecracker/src/api_server/parsed_request.rs
+++ b/src/firecracker/src/api_server/parsed_request.rs
@@ -276,7 +276,7 @@ pub(crate) enum RequestError {
#[error("API Resource IDs can only contain alphanumeric characters and underscores.")]
InvalidID,
// The HTTP method & request path combination is not valid.
- #[error("Invalid request method and/or path: {} {0}.", .1.to_str())]
+ #[error("Invalid request method and/or path: {} {}.", .1.to_str(), .0)]
InvalidPathMethod(String, Method),
// An error occurred when deserializing the json body of a request.
#[error("An error occurred when deserializing the json body of a request: {0}.")]
diff --git a/src/firecracker/swagger/firecracker.yaml b/src/firecracker/swagger/firecracker.yaml
index 6da2b8777f4..06f449db431 100644
--- a/src/firecracker/swagger/firecracker.yaml
+++ b/src/firecracker/swagger/firecracker.yaml
@@ -5,7 +5,7 @@ info:
The API is accessible through HTTP calls on specific URLs
carrying JSON modeled data.
The transport medium is a Unix Domain Socket.
- version: 1.10.0-dev
+ version: 1.11.0-dev
termsOfService: ""
contact:
email: "compute-capsule@amazon.com"
@@ -1028,6 +1028,9 @@ definitions:
properties:
cpu_template:
$ref: "#/definitions/CpuTemplate"
+ # gdb_socket_path:
+ # type: string
+ # description: Path to the GDB socket. Requires the gdb feature to be enabled.
smt:
type: boolean
description: Flag for enabling/disabling simultaneous multithreading. Can be enabled only on x86.
diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml
index b6499d0e73b..55b50efb785 100644
--- a/src/jailer/Cargo.toml
+++ b/src/jailer/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "jailer"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
authors = ["Amazon Firecracker team "]
edition = "2021"
description = "Process for starting Firecracker in production scenarios; applies a cgroup/namespace isolation barrier and then drops privileges."
@@ -12,11 +12,11 @@ name = "jailer"
bench = false
[dependencies]
-libc = "0.2.161"
+libc = "0.2.164"
log-instrument = { path = "../log-instrument", optional = true }
nix = { version = "0.29.0", default-features = false, features = ["dir"] }
-regex = { version = "1.11.0", default-features = false, features = ["std"] }
-thiserror = "1.0.64"
+regex = { version = "1.11.1", default-features = false, features = ["std"] }
+thiserror = "2.0.3"
vmm-sys-util = "0.12.1"
utils = { path = "../utils" }
diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml
index 85185601d60..fd25f4ffe08 100644
--- a/src/log-instrument-macros/Cargo.toml
+++ b/src/log-instrument-macros/Cargo.toml
@@ -11,9 +11,9 @@ proc-macro = true
bench = false
[dependencies]
-proc-macro2 = "1.0.88"
+proc-macro2 = "1.0.89"
quote = "1.0.37"
-syn = { version = "2.0.82", features = ["full", "extra-traits"] }
+syn = { version = "2.0.85", features = ["full", "extra-traits"] }
[lints]
workspace = true
diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml
index 42850d0413f..c944f5f346d 100644
--- a/src/rebase-snap/Cargo.toml
+++ b/src/rebase-snap/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rebase-snap"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
authors = ["Amazon Firecracker team "]
edition = "2021"
license = "Apache-2.0"
@@ -11,9 +11,9 @@ bench = false
[dependencies]
displaydoc = "0.2.5"
-libc = "0.2.161"
+libc = "0.2.164"
log-instrument = { path = "../log-instrument", optional = true }
-thiserror = "1.0.64"
+thiserror = "2.0.3"
vmm-sys-util = "0.12.1"
utils = { path = "../utils" }
diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml
index 85198ece731..1916a085b51 100644
--- a/src/seccompiler/Cargo.toml
+++ b/src/seccompiler/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "seccompiler"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
authors = ["Amazon Firecracker team "]
edition = "2021"
description = "Program that compiles multi-threaded seccomp-bpf filters expressed as JSON into raw BPF programs, serializing them and outputting them to a file."
@@ -18,11 +18,11 @@ bench = false
[dependencies]
bincode = "1.2.1"
displaydoc = "0.2.5"
-libc = "0.2.161"
+libc = "0.2.164"
log-instrument = { path = "../log-instrument", optional = true }
-serde = { version = "1.0.210", features = ["derive"] }
-serde_json = "1.0.132"
-thiserror = "1.0.64"
+serde = { version = "1.0.215", features = ["derive"] }
+serde_json = "1.0.133"
+thiserror = "2.0.3"
utils = { path = "../utils" }
diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml
index 68f470dfde8..022342d896f 100644
--- a/src/snapshot-editor/Cargo.toml
+++ b/src/snapshot-editor/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "snapshot-editor"
-version = "1.10.0-dev"
+version = "1.11.0-dev"
authors = ["Amazon Firecracker team "]
edition = "2021"
license = "Apache-2.0"
@@ -10,14 +10,14 @@ name = "snapshot-editor"
bench = false
[dependencies]
-clap = { version = "4.5.20", features = ["derive", "string"] }
+clap = { version = "4.5.21", features = ["derive", "string"] }
displaydoc = "0.2.5"
fc_utils = { package = "utils", path = "../utils" }
-libc = "0.2.161"
+libc = "0.2.164"
log-instrument = { path = "../log-instrument", optional = true }
semver = "1.0.23"
-thiserror = "1.0.64"
+thiserror = "2.0.3"
vmm = { path = "../vmm" }
vmm-sys-util = "0.12.1"
diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml
index 451a8ee72cc..2514ee05b0b 100644
--- a/src/utils/Cargo.toml
+++ b/src/utils/Cargo.toml
@@ -11,15 +11,15 @@ bench = false
[dependencies]
derive_more = { version = "1.0.0", default-features = false, features = ["from"] }
displaydoc = "0.2.5"
-libc = "0.2.161"
+libc = "0.2.164"
log-instrument = { path = "../log-instrument", optional = true }
-serde = { version = "1.0.210", features = ["derive"] }
-thiserror = "1.0.64"
-vm-memory = { version = "0.15.0", features = ["backend-mmap", "backend-bitmap"] }
+serde = { version = "1.0.215", features = ["derive"] }
+thiserror = "2.0.3"
+vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] }
vmm-sys-util = "0.12.1"
[dev-dependencies]
-serde_json = "1.0.132"
+serde_json = "1.0.133"
[features]
tracing = ["log-instrument"]
diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml
index 4fc2551190e..070cae5088f 100644
--- a/src/vmm/Cargo.toml
+++ b/src/vmm/Cargo.toml
@@ -12,7 +12,7 @@ bench = false
acpi_tables = { path = "../acpi-tables" }
aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] }
arrayvec = { version = "0.7.6", optional = true }
-aws-lc-rs = { version = "1.10.0", features = ["bindgen"] }
+aws-lc-rs = { version = "1.11.0", features = ["bindgen"] }
base64 = "0.22.1"
bincode = "1.2.1"
bitflags = "2.6.0"
@@ -20,13 +20,13 @@ crc64 = "2.0.0"
derive_more = { version = "1.0.0", default-features = false, features = ["from", "display"] }
displaydoc = "0.2.5"
event-manager = "0.4.0"
-gdbstub = { version = "0.7.2", optional = true }
+gdbstub = { version = "0.7.3", optional = true }
gdbstub_arch = { version = "0.3.1", optional = true }
-kvm-bindings = { version = "0.9.1", features = ["fam-wrappers", "serde"] }
-kvm-ioctls = "0.18.0"
+kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] }
+kvm-ioctls = "0.19.0"
lazy_static = "1.5.0"
-libc = "0.2.161"
-linux-loader = "0.12.0"
+libc = "0.2.164"
+linux-loader = "0.13.0"
log = { version = "0.4.22", features = ["std", "serde"] }
log-instrument = { path = "../log-instrument", optional = true }
memfd = "0.6.3"
@@ -34,19 +34,19 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http" }
seccompiler = { path = "../seccompiler" }
semver = { version = "1.0.23", features = ["serde"] }
-serde = { version = "1.0.210", features = ["derive", "rc"] }
-serde_json = "1.0.132"
+serde = { version = "1.0.215", features = ["derive", "rc"] }
+serde_json = "1.0.133"
slab = "0.4.7"
-thiserror = "1.0.64"
+thiserror = "2.0.3"
timerfd = "1.5.0"
userfaultfd = "0.8.1"
utils = { path = "../utils" }
-vhost = { version = "0.12.0", features = ["vhost-user-frontend"] }
+vhost = { version = "0.13.0", features = ["vhost-user-frontend"] }
vm-allocator = "0.1.0"
-vm-memory = { version = "0.15.0", features = ["backend-mmap", "backend-bitmap"] }
+vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] }
vm-superio = "0.8.0"
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }
-zerocopy = { version = "0.8.6" }
+zerocopy = { version = "0.8.10" }
[target.'cfg(target_arch = "aarch64")'.dependencies]
vm-fdt = "0.3.0"
diff --git a/src/vmm/src/arch/aarch64/gic/gicv2/regs/mod.rs b/src/vmm/src/arch/aarch64/gic/gicv2/regs/mod.rs
index 6e85b144a26..a0c0e2c8fac 100644
--- a/src/vmm/src/arch/aarch64/gic/gicv2/regs/mod.rs
+++ b/src/vmm/src/arch/aarch64/gic/gicv2/regs/mod.rs
@@ -41,6 +41,8 @@ pub fn restore_state(fd: &DeviceFd, mpidrs: &[u64], state: &GicState) -> Result<
#[cfg(test)]
mod tests {
+ #![allow(clippy::undocumented_unsafe_blocks)]
+
use kvm_ioctls::Kvm;
use super::*;
@@ -79,7 +81,9 @@ mod tests {
addr: &val as *const u32 as u64,
flags: 0,
};
- gic_fd.get_device_attr(&mut gic_dist_attr).unwrap();
+ unsafe {
+ gic_fd.get_device_attr(&mut gic_dist_attr).unwrap();
+ }
// The second value from the list of distributor registers is the value of the GICD_STATUSR
// register. We assert that the one saved in the bitmap is the same with the one we
diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/mod.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/mod.rs
index ba1c78dadc9..31261f647fc 100644
--- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/mod.rs
+++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/mod.rs
@@ -46,6 +46,8 @@ pub fn restore_state(fd: &DeviceFd, mpidrs: &[u64], state: &GicState) -> Result<
#[cfg(test)]
mod tests {
+ #![allow(clippy::undocumented_unsafe_blocks)]
+
use kvm_ioctls::Kvm;
use super::*;
@@ -81,7 +83,9 @@ mod tests {
addr: &val as *const u32 as u64,
flags: 0,
};
- gic_fd.get_device_attr(&mut gic_dist_attr).unwrap();
+ unsafe {
+ gic_fd.get_device_attr(&mut gic_dist_attr).unwrap();
+ }
// The second value from the list of distributor registers is the value of the GICD_STATUSR
// register. We assert that the one saved in the bitmap is the same with the one we
diff --git a/src/vmm/src/arch/aarch64/gic/regs.rs b/src/vmm/src/arch/aarch64/gic/regs.rs
index 88c4d68c15c..60987cc973d 100644
--- a/src/vmm/src/arch/aarch64/gic/regs.rs
+++ b/src/vmm/src/arch/aarch64/gic/regs.rs
@@ -81,8 +81,12 @@ pub(crate) trait VgicRegEngine {
let mut data = Vec::with_capacity(reg.iter::().count());
for offset in reg.iter::() {
let mut val = Self::RegChunk::default();
- fd.get_device_attr(&mut Self::kvm_device_attr(offset, &mut val, mpidr))
- .map_err(|err| GicError::DeviceAttribute(err, false, Self::group()))?;
+ // SAFETY: `val` is a mutable memory location sized correctly for the attribute we're
+ // requesting
+ unsafe {
+ fd.get_device_attr(&mut Self::kvm_device_attr(offset, &mut val, mpidr))
+ .map_err(|err| GicError::DeviceAttribute(err, false, Self::group()))?;
+ }
data.push(val);
}
diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs
index fee6be35b4f..1f52fdad063 100644
--- a/src/vmm/src/builder.rs
+++ b/src/vmm/src/builder.rs
@@ -346,8 +346,8 @@ pub fn build_microvm_for_boot(
let vmm = Arc::new(Mutex::new(vmm));
#[cfg(feature = "gdb")]
- if let Some(gdb_socket_addr) = &vm_resources.gdb_socket_addr {
- gdb::gdb_thread(vmm.clone(), vcpu_fds, gdb_rx, entry_addr, gdb_socket_addr)
+ if let Some(gdb_socket_path) = &vm_resources.vm_config.gdb_socket_path {
+ gdb::gdb_thread(vmm.clone(), vcpu_fds, gdb_rx, entry_addr, gdb_socket_path)
.map_err(GdbServer)?;
} else {
debug!("No GDB socket provided not starting gdb server.");
diff --git a/src/vmm/src/devices/virtio/iov_deque.rs b/src/vmm/src/devices/virtio/iov_deque.rs
index 3dff1e04d71..51bf28a49eb 100644
--- a/src/vmm/src/devices/virtio/iov_deque.rs
+++ b/src/vmm/src/devices/virtio/iov_deque.rs
@@ -6,7 +6,6 @@ use std::os::fd::AsRawFd;
use libc::{c_int, c_void, iovec, off_t, size_t};
use memfd;
-use super::queue::FIRECRACKER_MAX_QUEUE_SIZE;
use crate::arch::PAGE_SIZE;
#[derive(Debug, thiserror::Error, displaydoc::Display)]
@@ -69,26 +68,42 @@ pub enum IovDequeError {
//
// Like that, the elements stored in the buffer are always laid out in contiguous virtual memory,
// so making a slice out of them does not require any copies.
+//
+// The `L` const generic determines the maximum number of `iovec` elements the queue should hold.
+//
+// ```Rust
+// pub struct iovec {
+// pub iov_base: *mut ::c_void,
+// pub iov_len: ::size_t,
+// }
+// ```
+//
+// This value must be a multiple of 256 because this is the maximum number of `iovec` can fit into
+// 1 memory page: 256 * sizeof(iovec) == 4096 == PAGE_SIZE. IovDeque only operates with `PAGE_SIZE`
+// granularity.
#[derive(Debug)]
-pub struct IovDeque {
+pub struct IovDeque {
pub iov: *mut libc::iovec,
pub start: u16,
pub len: u16,
}
// SAFETY: This is `Send`. We hold sole ownership of the underlying buffer.
-unsafe impl Send for IovDeque {}
+unsafe impl Send for IovDeque {}
+
+impl IovDeque {
+ const BYTES: usize = L as usize * std::mem::size_of::();
+ const _ASSERT: () = assert!(Self::BYTES % PAGE_SIZE == 0);
-impl IovDeque {
/// Create a [`memfd`] object that represents a single physical page
fn create_memfd() -> Result {
// Create a sealable memfd.
let opts = memfd::MemfdOptions::default().allow_sealing(true);
- let mfd = opts.create("sized-1K")?;
+ let mfd = opts.create("iov_deque")?;
// Resize to system page size.
mfd.as_file()
- .set_len(PAGE_SIZE.try_into().unwrap())
+ .set_len(Self::BYTES.try_into().unwrap())
.map_err(IovDequeError::MemfdResize)?;
// Add seals to prevent further resizing.
@@ -121,35 +136,13 @@ impl IovDeque {
/// Allocate memory for our ring buffer
///
- /// This will allocate exactly two pages of virtual memory. In order to implement the
- /// optimization that allows us to always have elements in contiguous memory we need
- /// allocations at the granularity of `PAGE_SIZE`. Now, our queues are at maximum 256
- /// descriptors long and `struct iovec` looks like this:
- ///
- /// ```Rust
- /// pub struct iovec {
- /// pub iov_base: *mut ::c_void,
- /// pub iov_len: ::size_t,
- /// }
- /// ```
- ///
- /// so, it's 16 bytes long. As a result, we need a single page for holding the actual data of
- /// our buffer.
+ /// This will allocate 2 * `Self::BYTES` bytes of virtual memory.
fn allocate_ring_buffer_memory() -> Result<*mut c_void, IovDequeError> {
- // The fact that we allocate two pages is due to the size of `struct iovec` times our queue
- // size equals the page size. Add here a debug assertion to reflect that and ensure that we
- // will adapt our logic if the assumption changes in the future.
- const {
- assert!(
- std::mem::size_of::() * FIRECRACKER_MAX_QUEUE_SIZE as usize == PAGE_SIZE
- );
- }
-
// SAFETY: We are calling the system call with valid arguments
unsafe {
Self::mmap(
std::ptr::null_mut(),
- PAGE_SIZE * 2,
+ Self::BYTES * 2,
libc::PROT_NONE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
@@ -169,7 +162,7 @@ impl IovDeque {
let _ = unsafe {
Self::mmap(
buffer,
- PAGE_SIZE,
+ Self::BYTES,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED | libc::MAP_FIXED,
raw_memfd,
@@ -180,19 +173,17 @@ impl IovDeque {
// Map the second page of virtual memory to the physical page described by the memfd object
//
// SAFETY: This is safe because:
- // * Both `buffer` and the result of `buffer.add(PAGE_SIZE)` are within bounds of the
+ // * Both `buffer` and the result of `buffer.add(Self::BYTES)` are within bounds of the
// allocation we got from `Self::allocate_ring_buffer_memory`.
- // * The computed offset is `PAGE_SIZE * size_of::() == PAGE_SIZE bytes` which fits
- // in `isize`
// * The resulting pointer is the beginning of the second page of our allocation, so it
// doesn't wrap around the address space.
- let next_page = unsafe { buffer.add(PAGE_SIZE) };
+ let next_page = unsafe { buffer.add(Self::BYTES) };
// SAFETY: We are calling the system call with valid arguments
let _ = unsafe {
Self::mmap(
next_page,
- PAGE_SIZE,
+ Self::BYTES,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED | libc::MAP_FIXED,
raw_memfd,
@@ -216,7 +207,7 @@ impl IovDeque {
/// Returns `true` if the [`IovDeque`] is full, `false` otherwise
#[inline(always)]
pub fn is_full(&self) -> bool {
- self.len() == FIRECRACKER_MAX_QUEUE_SIZE
+ self.len() == L
}
/// Resets the queue, dropping all its elements.
@@ -261,8 +252,8 @@ impl IovDeque {
self.start += nr_iovecs;
self.len -= nr_iovecs;
- if self.start >= FIRECRACKER_MAX_QUEUE_SIZE {
- self.start -= FIRECRACKER_MAX_QUEUE_SIZE;
+ if self.start >= L {
+ self.start -= L;
}
}
@@ -318,11 +309,11 @@ impl IovDeque {
}
}
-impl Drop for IovDeque {
+impl Drop for IovDeque {
fn drop(&mut self) {
// SAFETY: We are passing an address that we got from a previous allocation of `2 *
- // PAGE_SIZE` bytes by calling mmap
- let _ = unsafe { libc::munmap(self.iov.cast(), PAGE_SIZE * 2) };
+ // Self::BYTES` bytes by calling mmap
+ let _ = unsafe { libc::munmap(self.iov.cast(), Self::BYTES * 2) };
}
}
@@ -330,7 +321,9 @@ impl Drop for IovDeque {
mod tests {
use libc::iovec;
- use super::IovDeque;
+ // Redefine `IovDeque` with specific length. Otherwise
+ // Rust will not know what to do.
+ type IovDeque = super::IovDeque<256>;
#[test]
fn test_new() {
diff --git a/src/vmm/src/devices/virtio/iovec.rs b/src/vmm/src/devices/virtio/iovec.rs
index 064660a4b54..2161d7273ef 100644
--- a/src/vmm/src/devices/virtio/iovec.rs
+++ b/src/vmm/src/devices/virtio/iovec.rs
@@ -11,6 +11,7 @@ use vm_memory::{
};
use super::iov_deque::{IovDeque, IovDequeError};
+use super::queue::FIRECRACKER_MAX_QUEUE_SIZE;
use crate::devices::virtio::queue::DescriptorChain;
use crate::vstate::memory::GuestMemoryMmap;
@@ -223,10 +224,11 @@ pub struct ParsedDescriptorChain {
/// It describes a write-only buffer passed to us by the guest that is scattered across multiple
/// memory regions. Additionally, this wrapper provides methods that allow reading arbitrary ranges
/// of data from that buffer.
+/// `L` const generic value must be a multiple of 256 as required by the `IovDeque` requirements.
#[derive(Debug)]
-pub struct IoVecBufferMut {
+pub struct IoVecBufferMut {
// container of the memory regions included in this IO vector
- pub vecs: IovDeque,
+ pub vecs: IovDeque,
// Total length of the IoVecBufferMut
// We use `u32` here because we use this type in devices which
// should not give us huge buffers. In any case this
@@ -236,9 +238,9 @@ pub struct IoVecBufferMut {
// SAFETY: `IoVecBufferMut` doesn't allow for interior mutability and no shared ownership is
// possible as it doesn't implement clone
-unsafe impl Send for IoVecBufferMut {}
+unsafe impl Send for IoVecBufferMut {}
-impl IoVecBufferMut {
+impl IoVecBufferMut {
/// Append a `DescriptorChain` in this `IoVecBufferMut`
///
/// # Safety
@@ -477,9 +479,15 @@ mod tests {
use libc::{c_void, iovec};
use vm_memory::VolatileMemoryError;
- use super::{IoVecBuffer, IoVecBufferMut};
+ use super::IoVecBuffer;
+ // Redefine `IoVecBufferMut` with specific length. Otherwise
+ // Rust will not know what to do.
+ type IoVecBufferMutDefault = super::IoVecBufferMut;
+
use crate::devices::virtio::iov_deque::IovDeque;
- use crate::devices::virtio::queue::{Queue, VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE};
+ use crate::devices::virtio::queue::{
+ Queue, FIRECRACKER_MAX_QUEUE_SIZE, VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE,
+ };
use crate::devices::virtio::test_utils::VirtQueue;
use crate::test_utils::multi_region_mem;
use crate::vstate::memory::{Bytes, GuestAddress, GuestMemoryMmap};
@@ -514,7 +522,7 @@ mod tests {
}
}
- impl From<&mut [u8]> for IoVecBufferMut {
+ impl From<&mut [u8]> for super::IoVecBufferMut {
fn from(buf: &mut [u8]) -> Self {
let mut vecs = IovDeque::new().unwrap();
vecs.push_back(iovec {
@@ -529,7 +537,7 @@ mod tests {
}
}
- impl From> for IoVecBufferMut {
+ impl From> for super::IoVecBufferMut {
fn from(buffer: Vec<&mut [u8]>) -> Self {
let mut len = 0;
let mut vecs = IovDeque::new().unwrap();
@@ -608,12 +616,12 @@ mod tests {
let (mut q, _) = read_only_chain(&mem);
let head = q.pop().unwrap();
// SAFETY: This descriptor chain is only loaded into one buffer
- unsafe { IoVecBufferMut::from_descriptor_chain(&mem, head).unwrap_err() };
+ unsafe { IoVecBufferMutDefault::from_descriptor_chain(&mem, head).unwrap_err() };
let (mut q, _) = write_only_chain(&mem);
let head = q.pop().unwrap();
// SAFETY: This descriptor chain is only loaded into one buffer
- unsafe { IoVecBufferMut::from_descriptor_chain(&mem, head).unwrap() };
+ unsafe { IoVecBufferMutDefault::from_descriptor_chain(&mem, head).unwrap() };
}
#[test]
@@ -634,7 +642,8 @@ mod tests {
let head = q.pop().unwrap();
// SAFETY: This descriptor chain is only loaded once in this test
- let mut iovec = unsafe { IoVecBufferMut::from_descriptor_chain(&mem, head).unwrap() };
+ let mut iovec =
+ unsafe { IoVecBufferMutDefault::from_descriptor_chain(&mem, head).unwrap() };
assert_eq!(iovec.len(), 4 * 64);
// We are creating a new queue where we can get descriptors from. Probably, this is not
@@ -711,7 +720,8 @@ mod tests {
let head = q.pop().unwrap();
// SAFETY: This descriptor chain is only loaded into one buffer
- let mut iovec = unsafe { IoVecBufferMut::from_descriptor_chain(&mem, head).unwrap() };
+ let mut iovec =
+ unsafe { IoVecBufferMutDefault::from_descriptor_chain(&mem, head).unwrap() };
let buf = vec![0u8, 1, 2, 3, 4];
// One test vector for each part of the chain
@@ -804,9 +814,14 @@ mod verification {
use vm_memory::bitmap::BitmapSlice;
use vm_memory::VolatileSlice;
- use super::{IoVecBuffer, IoVecBufferMut};
- use crate::arch::PAGE_SIZE;
+ use super::IoVecBuffer;
use crate::devices::virtio::iov_deque::IovDeque;
+ // Redefine `IoVecBufferMut` and `IovDeque` with specific length. Otherwise
+ // Rust will not know what to do.
+ type IoVecBufferMutDefault = super::IoVecBufferMut;
+ type IovDequeDefault = IovDeque;
+
+ use crate::arch::PAGE_SIZE;
use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE;
// Maximum memory size to use for our buffers. For the time being 1KB.
@@ -837,7 +852,7 @@ mod verification {
///
/// This stub helps imitate the effect of mirroring without all the elaborate memory
/// allocation trick.
- pub fn push_back(deque: &mut IovDeque, iov: iovec) {
+ pub fn push_back(deque: &mut IovDeque, iov: iovec) {
// This should NEVER happen, since our ring buffer is as big as the maximum queue size.
// We also check for the sanity of the VirtIO queues, in queue.rs, which means that if
// we ever try to add something in a full ring buffer, there is an internal
@@ -849,10 +864,10 @@ mod verification {
);
let offset = (deque.start + deque.len) as usize;
- let mirror = if offset >= FIRECRACKER_MAX_QUEUE_SIZE as usize {
- offset - FIRECRACKER_MAX_QUEUE_SIZE as usize
+ let mirror = if offset >= L as usize {
+ offset - L as usize
} else {
- offset + FIRECRACKER_MAX_QUEUE_SIZE as usize
+ offset + L as usize
};
// SAFETY: self.iov is a valid pointer and `self.start + self.len` is within range (we
@@ -893,7 +908,7 @@ mod verification {
}
}
- fn create_iov_deque() -> IovDeque {
+ fn create_iov_deque() -> IovDequeDefault {
// SAFETY: safe because the layout has non-zero size
let mem = unsafe {
std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked(
@@ -901,14 +916,14 @@ mod verification {
PAGE_SIZE,
))
};
- IovDeque {
+ IovDequeDefault {
iov: mem.cast(),
start: kani::any_where(|&start| start < FIRECRACKER_MAX_QUEUE_SIZE),
len: 0,
}
}
- fn create_iovecs_mut(mem: *mut u8, size: usize, nr_descs: usize) -> (IovDeque, u32) {
+ fn create_iovecs_mut(mem: *mut u8, size: usize, nr_descs: usize) -> (IovDequeDefault, u32) {
let mut vecs = create_iov_deque();
let mut len = 0u32;
for _ in 0..nr_descs {
@@ -928,7 +943,7 @@ mod verification {
(vecs, len)
}
- impl IoVecBufferMut {
+ impl IoVecBufferMutDefault {
fn any_of_length(nr_descs: usize) -> Self {
// We only write into `IoVecBufferMut` objects, so we can simply create a guest memory
// object initialized to zeroes, trying to be nice to Kani.
@@ -1021,7 +1036,7 @@ mod verification {
#[kani::stub(IovDeque::push_back, stubs::push_back)]
fn verify_write_to_iovec() {
for nr_descs in 0..MAX_DESC_LENGTH {
- let mut iov_mut = IoVecBufferMut::any_of_length(nr_descs);
+ let mut iov_mut = IoVecBufferMutDefault::any_of_length(nr_descs);
let mut buf = kani::vec::any_vec::();
let offset: u32 = kani::any();
diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs
index deb6976b2af..818fed86a30 100755
--- a/src/vmm/src/devices/virtio/net/device.rs
+++ b/src/vmm/src/devices/virtio/net/device.rs
@@ -14,6 +14,7 @@ use libc::{iovec, EAGAIN};
use log::error;
use vmm_sys_util::eventfd::EventFd;
+use super::NET_QUEUE_MAX_SIZE;
use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice};
use crate::devices::virtio::gen::virtio_blk::VIRTIO_F_VERSION_1;
use crate::devices::virtio::gen::virtio_net::{
@@ -30,7 +31,7 @@ use crate::devices::virtio::net::tap::Tap;
use crate::devices::virtio::net::{
gen, NetError, NetQueue, MAX_BUFFER_SIZE, NET_QUEUE_SIZES, RX_INDEX, TX_INDEX,
};
-use crate::devices::virtio::queue::{DescriptorChain, Queue, FIRECRACKER_MAX_QUEUE_SIZE};
+use crate::devices::virtio::queue::{DescriptorChain, Queue};
use crate::devices::virtio::{ActivateError, TYPE_NET};
use crate::devices::{report_net_event_fail, DeviceError};
use crate::dumbo::pdu::arp::ETH_IPV4_FRAME_LEN;
@@ -104,7 +105,7 @@ pub struct RxBuffers {
pub min_buffer_size: u32,
// An [`IoVecBufferMut`] covering all the memory we have available for receiving network
// frames.
- pub iovec: IoVecBufferMut,
+ pub iovec: IoVecBufferMut,
// A map of which part of the memory belongs to which `DescriptorChain` object
pub parsed_descriptors: VecDeque,
// Buffers that we have used and they are ready to be given back to the guest.
@@ -118,7 +119,7 @@ impl RxBuffers {
Ok(Self {
min_buffer_size: 0,
iovec: IoVecBufferMut::new()?,
- parsed_descriptors: VecDeque::with_capacity(FIRECRACKER_MAX_QUEUE_SIZE.into()),
+ parsed_descriptors: VecDeque::with_capacity(NET_QUEUE_MAX_SIZE.into()),
used_descriptors: 0,
used_bytes: 0,
})
@@ -2152,7 +2153,7 @@ pub mod tests {
// Test RX bandwidth rate limiting
{
// create bandwidth rate limiter that allows 2000 bytes/s with bucket size 1000 bytes
- let mut rl = RateLimiter::new(1000, 0, 500, 0, 0, 0).unwrap();
+ let mut rl = RateLimiter::new(1000, 0, 1000, 0, 0, 0).unwrap();
// set up RX
assert!(th.net().rx_buffer.used_descriptors == 0);
@@ -2194,9 +2195,9 @@ pub mod tests {
assert_eq!(th.net().metrics.rx_rate_limiter_throttled.count(), 2);
}
- // wait for 500ms to give the rate-limiter timer a chance to replenish
- // wait for an extra 500ms to make sure the timerfd event makes its way from the kernel
- thread::sleep(Duration::from_millis(1000));
+ // wait for 1000ms to give the rate-limiter timer a chance to replenish
+ // wait for an extra 1000ms to make sure the timerfd event makes its way from the kernel
+ thread::sleep(Duration::from_millis(2000));
// following RX procedure should succeed because bandwidth should now be available
{
@@ -2275,7 +2276,7 @@ pub mod tests {
// Test RX ops rate limiting
{
// create ops rate limiter that allows 2 ops/s with bucket size 1 ops
- let mut rl = RateLimiter::new(0, 0, 0, 1, 0, 500).unwrap();
+ let mut rl = RateLimiter::new(0, 0, 0, 1, 0, 1000).unwrap();
// set up RX
assert!(th.net().rx_buffer.used_descriptors == 0);
@@ -2318,9 +2319,9 @@ pub mod tests {
assert_eq!(th.rxq.used.idx.get(), 0);
}
- // wait for 500ms to give the rate-limiter timer a chance to replenish
- // wait for an extra 500ms to make sure the timerfd event makes its way from the kernel
- thread::sleep(Duration::from_millis(1000));
+ // wait for 1000ms to give the rate-limiter timer a chance to replenish
+ // wait for an extra 1000ms to make sure the timerfd event makes its way from the kernel
+ thread::sleep(Duration::from_millis(2000));
// following RX procedure should succeed because ops should now be available
{
diff --git a/src/vmm/src/devices/virtio/net/mod.rs b/src/vmm/src/devices/virtio/net/mod.rs
index e8a3f86ac72..4bc5b896601 100644
--- a/src/vmm/src/devices/virtio/net/mod.rs
+++ b/src/vmm/src/devices/virtio/net/mod.rs
@@ -5,13 +5,13 @@
use std::io;
-use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE;
-
+/// Maximum size of the queue for network device.
+pub const NET_QUEUE_MAX_SIZE: u16 = 256;
/// Maximum size of the frame buffers handled by this device.
pub const MAX_BUFFER_SIZE: usize = 65562;
/// The number of queues of the network device.
pub const NET_NUM_QUEUES: usize = 2;
-pub const NET_QUEUE_SIZES: [u16; NET_NUM_QUEUES] = [FIRECRACKER_MAX_QUEUE_SIZE; NET_NUM_QUEUES];
+pub const NET_QUEUE_SIZES: [u16; NET_NUM_QUEUES] = [NET_QUEUE_MAX_SIZE; NET_NUM_QUEUES];
/// The index of the rx queue from Net device queues/queues_evts vector.
pub const RX_INDEX: usize = 0;
/// The index of the tx queue from Net device queues/queues_evts vector.
diff --git a/src/vmm/src/devices/virtio/net/persist.rs b/src/vmm/src/devices/virtio/net/persist.rs
index 51394af2d4e..fb62dcb0abe 100644
--- a/src/vmm/src/devices/virtio/net/persist.rs
+++ b/src/vmm/src/devices/virtio/net/persist.rs
@@ -10,10 +10,9 @@ use std::sync::{Arc, Mutex};
use serde::{Deserialize, Serialize};
use super::device::{Net, RxBuffers};
-use super::{TapError, NET_NUM_QUEUES, RX_INDEX};
+use super::{TapError, NET_NUM_QUEUES, NET_QUEUE_MAX_SIZE, RX_INDEX};
use crate::devices::virtio::device::DeviceState;
use crate::devices::virtio::persist::{PersistError as VirtioStateError, VirtioDeviceState};
-use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE;
use crate::devices::virtio::TYPE_NET;
use crate::mmds::data_store::Mmds;
use crate::mmds::ns::MmdsNetworkStack;
@@ -147,7 +146,7 @@ impl Persist<'_> for Net {
&constructor_args.mem,
TYPE_NET,
NET_NUM_QUEUES,
- FIRECRACKER_MAX_QUEUE_SIZE,
+ NET_QUEUE_MAX_SIZE,
)?;
net.irq_trigger.irq_status = Arc::new(AtomicU32::new(state.virtio_state.interrupt_status));
net.avail_features = state.virtio_state.avail_features;
diff --git a/src/vmm/src/devices/virtio/net/tap.rs b/src/vmm/src/devices/virtio/net/tap.rs
index 4d1757edc8e..32c665e1c31 100644
--- a/src/vmm/src/devices/virtio/net/tap.rs
+++ b/src/vmm/src/devices/virtio/net/tap.rs
@@ -219,10 +219,13 @@ pub mod tests {
use std::os::unix::ffi::OsStrExt;
use super::*;
- use crate::devices::virtio::iovec::IoVecBufferMut;
use crate::devices::virtio::net::gen;
use crate::devices::virtio::net::test_utils::{enable, if_index, TapTrafficSimulator};
+ // Redefine `IoVecBufferMut` with specific length. Otherwise
+ // Rust will not know what to do.
+ type IoVecBufferMut = crate::devices::virtio::iovec::IoVecBufferMut<256>;
+
// The size of the virtio net header
const VNET_HDR_SIZE: usize = 10;
diff --git a/src/vmm/src/devices/virtio/queue.rs b/src/vmm/src/devices/virtio/queue.rs
index b80b2571c12..39ccef1f1ee 100644
--- a/src/vmm/src/devices/virtio/queue.rs
+++ b/src/vmm/src/devices/virtio/queue.rs
@@ -700,7 +700,6 @@ mod verification {
use std::mem::ManuallyDrop;
use std::num::Wrapping;
- use vm_memory::guest_memory::GuestMemoryIterator;
use vm_memory::{GuestMemoryRegion, MemoryRegionAddress};
use super::*;
@@ -717,13 +716,8 @@ mod verification {
the_region: vm_memory::GuestRegionMmap,
}
- impl<'a> GuestMemoryIterator<'a, vm_memory::GuestRegionMmap> for ProofGuestMemory {
- type Iter = std::iter::Once<&'a vm_memory::GuestRegionMmap>;
- }
-
impl GuestMemory for ProofGuestMemory {
type R = vm_memory::GuestRegionMmap;
- type I = Self;
fn num_regions(&self) -> usize {
1
@@ -735,7 +729,7 @@ mod verification {
.map(|_| &self.the_region)
}
- fn iter(&self) -> >::Iter {
+ fn iter(&self) -> impl Iterator- {
std::iter::once(&self.the_region)
}
diff --git a/src/vmm/src/devices/virtio/rng/device.rs b/src/vmm/src/devices/virtio/rng/device.rs
index 664fad5724d..96513e49b26 100644
--- a/src/vmm/src/devices/virtio/rng/device.rs
+++ b/src/vmm/src/devices/virtio/rng/device.rs
@@ -442,7 +442,7 @@ mod tests {
let desc = entropy_dev.queues_mut()[RNG_QUEUE].pop().unwrap();
assert!(matches!(
// SAFETY: This descriptor chain is only loaded into one buffer
- unsafe { IoVecBufferMut::from_descriptor_chain(&mem, desc) },
+ unsafe { IoVecBufferMut::<256>::from_descriptor_chain(&mem, desc) },
Err(crate::devices::virtio::iovec::IoVecError::ReadOnlyDescriptor)
));
diff --git a/src/vmm/src/mmds/ns.rs b/src/vmm/src/mmds/ns.rs
index 09d73b21e99..8075df8cb91 100644
--- a/src/vmm/src/mmds/ns.rs
+++ b/src/vmm/src/mmds/ns.rs
@@ -81,8 +81,6 @@ impl MmdsNetworkStack {
mac_addr: MacAddr,
ipv4_addr: Ipv4Addr,
tcp_port: u16,
- max_connections: NonZeroUsize,
- max_pending_resets: NonZeroUsize,
mmds: Arc>,
) -> Self {
MmdsNetworkStack {
@@ -93,8 +91,8 @@ impl MmdsNetworkStack {
tcp_handler: TcpIPv4Handler::new(
ipv4_addr,
tcp_port,
- max_connections,
- max_pending_resets,
+ NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(),
+ NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(),
),
mmds,
}
@@ -105,14 +103,7 @@ impl MmdsNetworkStack {
let ipv4_addr = mmds_ipv4_addr.unwrap_or_else(|| Ipv4Addr::from(DEFAULT_IPV4_ADDR));
// The unwrap()s are safe because the given literals are greater than 0.
- Self::new(
- mac_addr,
- ipv4_addr,
- DEFAULT_TCP_PORT,
- NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(),
- NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(),
- mmds,
- )
+ Self::new(mac_addr, ipv4_addr, DEFAULT_TCP_PORT, mmds)
}
pub fn set_ipv4_addr(&mut self, ipv4_addr: Ipv4Addr) {
@@ -562,14 +553,8 @@ mod tests {
let ip = Ipv4Addr::from(DEFAULT_IPV4_ADDR);
let other_ip = Ipv4Addr::new(5, 6, 7, 8);
let mac = MacAddr::from_bytes_unchecked(&[0; 6]);
- let mut ns = MmdsNetworkStack::new(
- mac,
- ip,
- DEFAULT_TCP_PORT,
- NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(),
- NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(),
- Arc::new(Mutex::new(Mmds::default())),
- );
+ let mut ns =
+ MmdsNetworkStack::new_with_defaults(Some(ip), Arc::new(Mutex::new(Mmds::default())));
let mut eth =
EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_ARP).unwrap();
@@ -589,14 +574,8 @@ mod tests {
let ip = Ipv4Addr::from(DEFAULT_IPV4_ADDR);
let other_ip = Ipv4Addr::new(5, 6, 7, 8);
let mac = MacAddr::from_bytes_unchecked(&[0; 6]);
- let ns = MmdsNetworkStack::new(
- mac,
- ip,
- DEFAULT_TCP_PORT,
- NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(),
- NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(),
- Arc::new(Mutex::new(Mmds::default())),
- );
+ let ns =
+ MmdsNetworkStack::new_with_defaults(Some(ip), Arc::new(Mutex::new(Mmds::default())));
let mut eth =
EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_IPV4).unwrap();
@@ -615,14 +594,8 @@ mod tests {
let ip = Ipv4Addr::from(DEFAULT_IPV4_ADDR);
let other_ip = Ipv4Addr::new(5, 6, 7, 8);
let mac = MacAddr::from_bytes_unchecked(&[0; 6]);
- let mut ns = MmdsNetworkStack::new(
- mac,
- ip,
- DEFAULT_TCP_PORT,
- NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(),
- NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(),
- Arc::new(Mutex::new(Mmds::default())),
- );
+ let mut ns =
+ MmdsNetworkStack::new_with_defaults(Some(ip), Arc::new(Mutex::new(Mmds::default())));
// try IPv4 with detour_arp
let mut eth =
diff --git a/src/vmm/src/mmds/persist.rs b/src/vmm/src/mmds/persist.rs
index dc0113f8a5c..82feff79bc8 100644
--- a/src/vmm/src/mmds/persist.rs
+++ b/src/vmm/src/mmds/persist.rs
@@ -4,7 +4,6 @@
//! Defines the structures needed for saving/restoring MmdsNetworkStack.
use std::net::Ipv4Addr;
-use std::num::NonZeroUsize;
use std::sync::{Arc, Mutex};
use serde::{Deserialize, Serialize};
@@ -20,8 +19,6 @@ pub struct MmdsNetworkStackState {
mac_addr: [u8; MAC_ADDR_LEN as usize],
ipv4_addr: u32,
tcp_port: u16,
- max_connections: NonZeroUsize,
- max_pending_resets: NonZeroUsize,
}
impl Persist<'_> for MmdsNetworkStack {
@@ -37,8 +34,6 @@ impl Persist<'_> for MmdsNetworkStack {
mac_addr,
ipv4_addr: self.ipv4_addr.into(),
tcp_port: self.tcp_handler.local_port(),
- max_connections: self.tcp_handler.max_connections(),
- max_pending_resets: self.tcp_handler.max_pending_resets(),
}
}
@@ -50,8 +45,6 @@ impl Persist<'_> for MmdsNetworkStack {
MacAddr::from_bytes_unchecked(&state.mac_addr),
Ipv4Addr::from(state.ipv4_addr),
state.tcp_port,
- state.max_connections,
- state.max_pending_resets,
mmds,
))
}
@@ -83,13 +76,5 @@ mod tests {
restored_ns.tcp_handler.local_port(),
ns.tcp_handler.local_port()
);
- assert_eq!(
- restored_ns.tcp_handler.max_connections(),
- ns.tcp_handler.max_connections()
- );
- assert_eq!(
- restored_ns.tcp_handler.max_pending_resets(),
- ns.tcp_handler.max_pending_resets()
- );
}
}
diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs
index 6410e4d6c9b..5b01ed49c75 100644
--- a/src/vmm/src/persist.rs
+++ b/src/vmm/src/persist.rs
@@ -157,7 +157,7 @@ pub enum CreateSnapshotError {
}
/// Snapshot version
-pub const SNAPSHOT_VERSION: Version = Version::new(3, 0, 0);
+pub const SNAPSHOT_VERSION: Version = Version::new(5, 0, 0);
/// Creates a Microvm snapshot.
pub fn create_snapshot(
@@ -433,6 +433,8 @@ pub fn restore_from_snapshot(
cpu_template: Some(microvm_state.vm_info.cpu_template),
track_dirty_pages: Some(track_dirty_pages),
huge_pages: Some(microvm_state.vm_info.huge_pages),
+ #[cfg(feature = "gdb")]
+ gdb_socket_path: None,
})
.map_err(BuildMicrovmFromSnapshotError::VmUpdateConfig)?;
diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs
index 923225c6a8a..a4d15641975 100644
--- a/src/vmm/src/resources.rs
+++ b/src/vmm/src/resources.rs
@@ -86,9 +86,6 @@ pub struct VmmConfig {
vsock_device: Option,
#[serde(rename = "entropy")]
entropy_device: Option,
- #[cfg(feature = "gdb")]
- #[serde(rename = "gdb-socket")]
- gdb_socket_addr: Option,
}
/// A data structure that encapsulates the device configurations
@@ -117,9 +114,6 @@ pub struct VmResources {
pub mmds_size_limit: usize,
/// Whether or not to load boot timer device.
pub boot_timer: bool,
- #[cfg(feature = "gdb")]
- /// Configures the location of the GDB socket
- pub gdb_socket_addr: Option,
}
impl VmResources {
@@ -142,8 +136,6 @@ impl VmResources {
let mut resources: Self = Self {
mmds_size_limit,
- #[cfg(feature = "gdb")]
- gdb_socket_addr: vmm_config.gdb_socket_addr,
..Default::default()
};
if let Some(machine_config) = vmm_config.machine_config {
@@ -529,8 +521,6 @@ impl From<&VmResources> for VmmConfig {
net_devices: resources.net_builder.configs(),
vsock_device: resources.vsock.config(),
entropy_device: resources.entropy.config(),
- #[cfg(feature = "gdb")]
- gdb_socket_addr: resources.gdb_socket_addr.clone(),
}
}
}
@@ -640,8 +630,6 @@ mod tests {
boot_timer: false,
mmds_size_limit: HTTP_MAX_PAYLOAD_SIZE,
entropy: Default::default(),
- #[cfg(feature = "gdb")]
- gdb_socket_addr: None,
}
}
diff --git a/src/vmm/src/vmm_config/machine_config.rs b/src/vmm/src/vmm_config/machine_config.rs
index 3c657b9133c..8eee91c88be 100644
--- a/src/vmm/src/vmm_config/machine_config.rs
+++ b/src/vmm/src/vmm_config/machine_config.rs
@@ -111,6 +111,10 @@ pub struct MachineConfig {
/// Configures what page size Firecracker should use to back guest memory.
#[serde(default)]
pub huge_pages: HugePageConfig,
+ /// GDB socket address.
+ #[cfg(feature = "gdb")]
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub gdb_socket_path: Option,
}
impl Default for MachineConfig {
@@ -146,6 +150,10 @@ pub struct MachineConfigUpdate {
/// Configures what page size Firecracker should use to back guest memory.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub huge_pages: Option,
+ /// GDB socket address.
+ #[cfg(feature = "gdb")]
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub gdb_socket_path: Option,
}
impl MachineConfigUpdate {
@@ -166,6 +174,8 @@ impl From for MachineConfigUpdate {
cpu_template: cfg.cpu_template,
track_dirty_pages: Some(cfg.track_dirty_pages),
huge_pages: Some(cfg.huge_pages),
+ #[cfg(feature = "gdb")]
+ gdb_socket_path: cfg.gdb_socket_path,
}
}
}
@@ -185,6 +195,9 @@ pub struct VmConfig {
pub track_dirty_pages: bool,
/// Configures what page size Firecracker should use to back guest memory.
pub huge_pages: HugePageConfig,
+ /// GDB socket address.
+ #[cfg(feature = "gdb")]
+ pub gdb_socket_path: Option,
}
impl VmConfig {
@@ -238,6 +251,8 @@ impl VmConfig {
cpu_template,
track_dirty_pages: update.track_dirty_pages.unwrap_or(self.track_dirty_pages),
huge_pages: page_config,
+ #[cfg(feature = "gdb")]
+ gdb_socket_path: update.gdb_socket_path.clone(),
})
}
}
@@ -251,6 +266,8 @@ impl Default for VmConfig {
cpu_template: None,
track_dirty_pages: false,
huge_pages: HugePageConfig::None,
+ #[cfg(feature = "gdb")]
+ gdb_socket_path: None,
}
}
}
@@ -264,6 +281,8 @@ impl From<&VmConfig> for MachineConfig {
cpu_template: value.cpu_template.as_ref().map(|template| template.into()),
track_dirty_pages: value.track_dirty_pages,
huge_pages: value.huge_pages,
+ #[cfg(feature = "gdb")]
+ gdb_socket_path: value.gdb_socket_path.clone(),
}
}
}
diff --git a/tests/README.md b/tests/README.md
index 95a86215d9e..ea46ff56786 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -169,16 +169,21 @@ function to [`.buildkite/pipeline_perf.py`](../.buildkite/pipeline_perf.py). To
manually run an A/B-Test, use
```sh
-tools/devtool -y test --ab [optional arguments to ab_test.py] run --test
+tools/devtool -y test --ab [optional arguments to ab_test.py] run --test
```
-Here, _revision A_ and _revision B_ can be arbitrary git objects, such as commit
-SHAs, branches or tags. For example, to compare boottime of microVMs between
-Firecracker binaries compiled from the `main` branch and the `HEAD` of your
-current branch, run
+Here, _dir A_ and _dir B_ are directories containing firecracker and jailer
+binaries whose performance characteristics you wish to compare. You can use
+`./tools/devtool build --rev --release` to compile binaries from an
+arbitrary git object (commit SHAs, branches, tags etc.). This will create
+sub-directories in `build` containing the binaries. For example, to compare
+boottime of microVMs between Firecracker binaries compiled from the `main`
+branch and the `HEAD` of your current branch, run
```sh
-tools/devtool -y test --ab run main HEAD --test integration_tests/performance/test_boottime.py::test_boottime
+tools/devtool -y build --rev main --release
+tools/devtool -y build --rev HEAD --release
+tools/devtool -y test --ab -- run build/main build/HEAD --test integration_tests/performance/test_boottime.py::test_boottime
```
#### How to Write an A/B-Compatible Test and Common Pitfalls
@@ -298,9 +303,9 @@ that are pre-initialized with specific guest kernels and rootfs:
- `uvm_plain_any` is parametrized by the guest kernels
[supported](../docs/kernel-policy.md) by Firecracker and a read-only Ubuntu
- 22.04 squashfs as rootfs,
+ 24.04 squashfs as rootfs,
- `uvm_plain` yields a Firecracker process pre-initialized with a 5.10 kernel
- and the same Ubuntu 22.04 squashfs.
+ and the same Ubuntu 24.04 squashfs.
Generally, tests should use the former if you are testing some interaction
between the guest and Firecracker, while the latter should be used if
diff --git a/tests/conftest.py b/tests/conftest.py
index 8e4c2e2848e..8f4c2e51ff5 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -99,19 +99,7 @@ def record_props(request, record_property):
# Extract attributes from the docstrings
function_docstring = inspect.getdoc(request.function)
- description = []
- attributes = {}
- for line in function_docstring.split("\n"):
- # extract tags like @type, @issue, etc
- match = re.match(r"\s*@(?P\w+):\s*(?P\w+)", line)
- if match:
- attr, value = match["attr"], match["value"]
- attributes[attr] = value
- else:
- description.append(line)
- for attr_name, attr_value in attributes.items():
- record_property(attr_name, attr_value)
- record_property("description", "".join(description))
+ record_property("description", function_docstring)
def pytest_runtest_logreport(report):
@@ -319,14 +307,20 @@ def custom_cpu_template(request, record_property):
@pytest.fixture(
- params=list(static_cpu_templates_params()) + list(custom_cpu_templates_params())
+ params=[
+ pytest.param(None, id="NO_CPU_TMPL"),
+ *static_cpu_templates_params(),
+ *custom_cpu_templates_params(),
+ ],
)
def cpu_template_any(request, record_property):
- """This fixture combines static and custom CPU templates"""
- if "name" in request.param:
- record_property("custom_cpu_template", request.param["name"])
- else:
- record_property("static_cpu_template", request.param)
+ """This fixture combines no template, static and custom CPU templates"""
+ cpu_template_name = request.param
+ if request.param is None:
+ cpu_template_name = "None"
+ elif "name" in request.param:
+ cpu_template_name = request.param["name"]
+ record_property("cpu_template", cpu_template_name)
return request.param
@@ -394,27 +388,24 @@ def rootfs_fxt(request, record_property):
)
# Fixtures for all Ubuntu rootfs, and specific versions
-rootfs = pytest.fixture(rootfs_fxt, params=rootfs_params("*.squashfs"))
-rootfs_ubuntu_22 = pytest.fixture(
- rootfs_fxt, params=rootfs_params("ubuntu-22*.squashfs")
-)
+rootfs = pytest.fixture(rootfs_fxt, params=rootfs_params("ubuntu-24*.squashfs"))
rootfs_rw = pytest.fixture(rootfs_fxt, params=rootfs_params("*.ext4"))
@pytest.fixture
-def uvm_plain(microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22):
+def uvm_plain(microvm_factory, guest_kernel_linux_5_10, rootfs):
"""Create a vanilla VM, non-parametrized
kernel: 5.10
- rootfs: Ubuntu 22.04
+ rootfs: Ubuntu 24.04
"""
- return microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22)
+ return microvm_factory.build(guest_kernel_linux_5_10, rootfs)
@pytest.fixture
def uvm_plain_rw(microvm_factory, guest_kernel_linux_5_10, rootfs_rw):
"""Create a vanilla VM, non-parametrized
kernel: 5.10
- rootfs: Ubuntu 22.04
+ rootfs: Ubuntu 24.04
"""
return microvm_factory.build(guest_kernel_linux_5_10, rootfs_rw)
@@ -436,12 +427,24 @@ def artifact_dir():
@pytest.fixture
-def uvm_plain_any(microvm_factory, guest_kernel, rootfs_ubuntu_22):
+def uvm_plain_any(microvm_factory, guest_kernel, rootfs):
"""All guest kernels
kernel: all
- rootfs: Ubuntu 22.04
+ rootfs: Ubuntu 24.04
"""
- return microvm_factory.build(guest_kernel, rootfs_ubuntu_22)
+ return microvm_factory.build(guest_kernel, rootfs)
+
+
+guest_kernel_6_1_debug = pytest.fixture(
+ guest_kernel_fxt,
+ params=kernel_params("vmlinux-6.1*", artifact_dir=defs.ARTIFACT_DIR / "debug"),
+)
+
+
+@pytest.fixture
+def uvm_plain_debug(microvm_factory, guest_kernel_6_1_debug, rootfs_rw):
+ """VM running a kernel with debug/trace Kconfig options"""
+ return microvm_factory.build(guest_kernel_6_1_debug, rootfs_rw)
@pytest.fixture
diff --git a/tests/framework/ab_test.py b/tests/framework/ab_test.py
index b90cdfd1503..cf909d44fa6 100644
--- a/tests/framework/ab_test.py
+++ b/tests/framework/ab_test.py
@@ -21,19 +21,20 @@
of both invocations is the same, the test passes (with us being alerted to this situtation via a special pipeline that
does not block PRs). If not, it fails, preventing PRs from introducing new vulnerable dependencies.
"""
-import contextlib
import os
import statistics
from pathlib import Path
+from tempfile import TemporaryDirectory
from typing import Callable, List, Optional, TypeVar
import scipy
from framework import utils
+from framework.defs import FC_WORKSPACE_DIR
from framework.microvm import Microvm
from framework.utils import CommandReturn
from framework.with_filelock import with_filelock
-from host_tools.cargo_build import get_binary, get_firecracker_binaries
+from host_tools.cargo_build import DEFAULT_TARGET_DIR, get_firecracker_binaries
# Locally, this will always compare against main, even if we try to merge into, say, a feature branch.
# We might want to do a more sophisticated way to determine a "parent" branch here.
@@ -82,19 +83,41 @@ def git_ab_test(
(alternatively, your comparator can perform any required assertions and not return anything).
"""
- dir_a = git_clone(Path("../build") / a_revision, a_revision)
- result_a = test_runner(dir_a, True)
+ with TemporaryDirectory() as tmp_dir:
+ dir_a = git_clone(Path(tmp_dir) / a_revision, a_revision)
+ result_a = test_runner(dir_a, True)
- if b_revision:
- dir_b = git_clone(Path("../build") / b_revision, b_revision)
- else:
- # By default, pytest execution happens inside the `tests` subdirectory. Pass the repository root, as
- # documented.
- dir_b = Path.cwd().parent
- result_b = test_runner(dir_b, False)
+ if b_revision:
+ dir_b = git_clone(Path(tmp_dir) / b_revision, b_revision)
+ else:
+ # By default, pytest execution happens inside the `tests` subdirectory. Pass the repository root, as
+ # documented.
+ dir_b = Path.cwd().parent
+ result_b = test_runner(dir_b, False)
- comparison = comparator(result_a, result_b)
- return result_a, result_b, comparison
+ comparison = comparator(result_a, result_b)
+ return result_a, result_b, comparison
+
+
+DEFAULT_A_DIRECTORY = FC_WORKSPACE_DIR / "build" / "main"
+DEFAULT_B_DIRECTORY = FC_WORKSPACE_DIR / "build" / "cargo_target" / DEFAULT_TARGET_DIR
+
+
+def binary_ab_test(
+ test_runner: Callable[[Path, bool], T],
+ comparator: Callable[[T, T], U] = default_comparator,
+ *,
+ a_directory: Path = DEFAULT_A_DIRECTORY,
+ b_directory: Path = DEFAULT_B_DIRECTORY,
+):
+ """
+ Similar to `git_ab_test`, but instead of locally checking out different revisions, it operates on
+ directories containing firecracker/jailer binaries
+ """
+ result_a = test_runner(a_directory, True)
+ result_b = test_runner(b_directory, False)
+
+ return result_a, result_b, comparator(result_a, result_b)
def is_pr() -> bool:
@@ -153,7 +176,7 @@ def set_did_not_grow_comparator(
)
-def git_ab_test_guest_command(
+def precompiled_ab_test_guest_command(
microvm_factory: Callable[[Path, Path], Microvm],
command: str,
*,
@@ -163,22 +186,21 @@ def git_ab_test_guest_command(
):
"""The same as git_ab_test_command, but via SSH. The closure argument should setup a microvm using the passed
paths to firecracker and jailer binaries."""
+ b_directory = (
+ DEFAULT_B_DIRECTORY
+ if b_revision is None
+ else FC_WORKSPACE_DIR / "build" / b_revision
+ )
- @with_filelock
- def build_firecracker(workspace_dir):
- utils.check_output("./tools/release.sh --profile release", cwd=workspace_dir)
-
- def test_runner(workspace_dir, _is_a: bool):
- firecracker = get_binary("firecracker", workspace_dir=workspace_dir)
- if not firecracker.exists():
- build_firecracker(workspace_dir)
- bin_dir = firecracker.parent.resolve()
- firecracker, jailer = bin_dir / "firecracker", bin_dir / "jailer"
- microvm = microvm_factory(firecracker, jailer)
+ def test_runner(bin_dir, _is_a: bool):
+ microvm = microvm_factory(bin_dir / "firecracker", bin_dir / "jailer")
return microvm.ssh.run(command)
- (_, old_out, old_err), (_, new_out, new_err), the_same = git_ab_test(
- test_runner, comparator, a_revision=a_revision, b_revision=b_revision
+ (_, old_out, old_err), (_, new_out, new_err), the_same = binary_ab_test(
+ test_runner,
+ comparator,
+ a_directory=FC_WORKSPACE_DIR / "build" / a_revision,
+ b_directory=b_directory,
)
assert (
@@ -186,7 +208,7 @@ def test_runner(workspace_dir, _is_a: bool):
), f"The output of running command `{command}` changed:\nOld:\nstdout:\n{old_out}\nstderr\n{old_err}\n\nNew:\nstdout:\n{new_out}\nstderr:\n{new_err}"
-def git_ab_test_guest_command_if_pr(
+def precompiled_ab_test_guest_command_if_pr(
microvm_factory: Callable[[Path, Path], Microvm],
command: str,
*,
@@ -195,7 +217,9 @@ def git_ab_test_guest_command_if_pr(
):
"""The same as git_ab_test_command_if_pr, but via SSH"""
if is_pr():
- git_ab_test_guest_command(microvm_factory, command, comparator=comparator)
+ precompiled_ab_test_guest_command(
+ microvm_factory, command, comparator=comparator
+ )
return None
microvm = microvm_factory(*get_firecracker_binaries())
@@ -249,17 +273,3 @@ def git_clone(clone_path, commitish):
)
utils.check_output(f"git branch -D {branch_name}")
return clone_path
-
-
-# Once we upgrade to python 3.11, this will be in contextlib:
-# https://docs.python.org/3/library/contextlib.html#contextlib.chdir
-@contextlib.contextmanager
-def chdir(to):
- """Context manager that temporarily `chdir`s to the specified path"""
- cur = os.getcwd()
-
- try:
- os.chdir(to)
- yield
- finally:
- os.chdir(cur)
diff --git a/tests/framework/artifacts.py b/tests/framework/artifacts.py
index 0283be41941..77584f02129 100644
--- a/tests/framework/artifacts.py
+++ b/tests/framework/artifacts.py
@@ -8,7 +8,6 @@
from pathlib import Path
from typing import Iterator
-import packaging.version
import pytest
from framework.defs import ARTIFACT_DIR
@@ -33,12 +32,12 @@ def select_supported_kernels():
return supported_kernels
-def kernels(glob) -> Iterator:
+def kernels(glob, artifact_dir: Path = ARTIFACT_DIR) -> Iterator:
"""Return supported kernels as kernels supported by the current combination of kernel and
instance type.
"""
supported_kernels = select_supported_kernels()
- for kernel in sorted(ARTIFACT_DIR.rglob(glob)):
+ for kernel in sorted(artifact_dir.glob(glob)):
for kernel_regex in supported_kernels:
if re.fullmatch(kernel_regex, kernel.name):
yield kernel
@@ -50,9 +49,11 @@ def disks(glob) -> Iterator:
yield from sorted(ARTIFACT_DIR.glob(glob))
-def kernel_params(glob="vmlinux-*", select=kernels) -> Iterator:
+def kernel_params(
+ glob="vmlinux-*", select=kernels, artifact_dir=ARTIFACT_DIR
+) -> Iterator:
"""Return supported kernels"""
- for kernel in select(glob):
+ for kernel in select(glob, artifact_dir):
yield pytest.param(kernel, id=kernel.name)
@@ -98,9 +99,6 @@ def snapshot_version_tuple(self):
# independent of Firecracker versions. For these Firecracker versions, use
# the --snapshot-version Firecracker flag, to figure out which snapshot version
# it supports.
- # TODO: remove this check once all version up to (and including) 1.6.0 go out of support.
- if packaging.version.parse(self.version) < packaging.version.parse("1.7.0"):
- return self.version_tuple[:2] + (0,)
return (
check_output([self.path, "--snapshot-version"])
diff --git a/tests/framework/microvm_helpers.py b/tests/framework/microvm_helpers.py
index 4239eb2489f..f29ae84a9a0 100644
--- a/tests/framework/microvm_helpers.py
+++ b/tests/framework/microvm_helpers.py
@@ -222,3 +222,26 @@ def run_in_netns(cmd):
# add a route on the host for the clone address
run(f"ip route add {ingress_ipv4} via {veth_guest_ip}")
+
+ def trace_cmd_guest(self, fns, cmd, port=4321):
+ """Run trace-cmd on the guest, but transfer the data directly to the host."""
+ docker_apt_install("trace-cmd")
+ print("host> trace-cmd listen")
+ _proc = subprocess.Popen(
+ [
+ "ip",
+ "netns",
+ "exec",
+ self.vm.netns.id,
+ "trace-cmd",
+ "listen",
+ "-p",
+ str(port),
+ ]
+ )
+ print("guest> trace-cmd record")
+ host_ip = self.vm.iface["eth0"]["iface"].host_ip
+ _guest_ps = self.vm.ssh.run(
+ f"trace-cmd record -N {host_ip}:{port} -p function {" ".join(fns)} {cmd}"
+ )
+ return list(Path(".").glob("trace.*.dat"))
diff --git a/tests/framework/properties.py b/tests/framework/properties.py
index 07a52692a38..b40df56249e 100644
--- a/tests/framework/properties.py
+++ b/tests/framework/properties.py
@@ -48,11 +48,11 @@ def get_host_os(kv: str = None):
kv = platform.release()
parts = kv.split("-")
if len(parts) < 2:
- return None
+ return kv
misc = parts[1].split(".")
if len(misc) > 2 and misc[2] in {"amzn2", "amzn2023"}:
return misc[2]
- return None
+ return kv
class GlobalProps:
diff --git a/tests/framework/utils.py b/tests/framework/utils.py
index dbae40016ea..a8715f00e94 100644
--- a/tests/framework/utils.py
+++ b/tests/framework/utils.py
@@ -234,17 +234,14 @@ def _cpus(cls):
# - cgroupsv1: /cpuset.cpus
# - cgroupsv2: /cpuset.cpus.effective
# For more details, see https://docs.kernel.org/admin-guide/cgroup-v2.html#cpuset-interface-files
- cpulist = None
for path in [
Path("/sys/fs/cgroup/cpuset/cpuset.cpus"),
Path("/sys/fs/cgroup/cpuset.cpus.effective"),
]:
if path.exists():
- cpulist = path.read_text("ascii").strip()
- break
- else:
- raise RuntimeError("Could not find cgroups cpuset")
- return ListFormatParser(cpulist).parse()
+ return ListFormatParser(path.read_text("ascii").strip()).parse()
+
+ raise RuntimeError("Could not find cgroups cpuset")
class ListFormatParser:
diff --git a/tests/framework/utils_cpu_templates.py b/tests/framework/utils_cpu_templates.py
index 5badd7c640a..96bf197efda 100644
--- a/tests/framework/utils_cpu_templates.py
+++ b/tests/framework/utils_cpu_templates.py
@@ -42,18 +42,12 @@ def get_supported_cpu_templates():
SUPPORTED_CPU_TEMPLATES = get_supported_cpu_templates()
-# Custom CPU templates for Aarch64 for testing
-AARCH64_CUSTOM_CPU_TEMPLATES_G2 = ["v1n1"]
-AARCH64_CUSTOM_CPU_TEMPLATES_G3 = [
- "aarch64_with_sve_and_pac",
- "v1n1",
-]
-
def get_supported_custom_cpu_templates():
"""
Return the list of custom CPU templates supported by the platform.
"""
+ # pylint:disable=too-many-return-statements
host_linux = global_props.host_linux_version_tpl
match get_cpu_vendor(), global_props.cpu_codename:
@@ -65,9 +59,11 @@ def get_supported_custom_cpu_templates():
case CpuVendor.AMD, _:
return AMD_TEMPLATES
case CpuVendor.ARM, CpuModel.ARM_NEOVERSE_N1 if host_linux >= (6, 1):
- return AARCH64_CUSTOM_CPU_TEMPLATES_G2
+ return ["v1n1"]
case CpuVendor.ARM, CpuModel.ARM_NEOVERSE_V1 if host_linux >= (6, 1):
- return AARCH64_CUSTOM_CPU_TEMPLATES_G3
+ return ["v1n1", "aarch64_with_sve_and_pac"]
+ case CpuVendor.ARM, CpuModel.ARM_NEOVERSE_V1:
+ return ["aarch64_with_sve_and_pac"]
case _:
return []
diff --git a/tests/framework/utils_cpuid.py b/tests/framework/utils_cpuid.py
index 65e953f43ac..4303e3ba967 100644
--- a/tests/framework/utils_cpuid.py
+++ b/tests/framework/utils_cpuid.py
@@ -10,6 +10,8 @@
from framework.utils import check_output
from framework.utils_imdsv2 import imdsv2_get
+CPU_FEATURES_CMD = r"lscpu |grep -oP '^Flags:\s+\K.+'"
+
class CpuVendor(Enum):
"""CPU vendors enum."""
diff --git a/tests/framework/utils_drive.py b/tests/framework/utils_drive.py
index 2e67ff41f39..7bb623d73e0 100644
--- a/tests/framework/utils_drive.py
+++ b/tests/framework/utils_drive.py
@@ -23,17 +23,15 @@ class VhostUserBlkBackendType(Enum):
CROSVM = "Crosvm"
-def partuuid_and_disk_path(rootfs_ubuntu_22, disk_path):
+def partuuid_and_disk_path(rootfs, disk_path):
"""
We create a new file with specified path, get its partuuid and use it as a rootfs.
"""
- initial_size = rootfs_ubuntu_22.stat().st_size + 50 * MB
+ initial_size = rootfs.stat().st_size + 50 * MB
disk_path.touch()
os.truncate(disk_path, initial_size)
check_output(f"echo type=83 | sfdisk --no-tell-kernel {str(disk_path)}", shell=True)
- check_output(
- f"dd bs=1M seek=1 if={str(rootfs_ubuntu_22)} of={disk_path}", shell=True
- )
+ check_output(f"dd bs=1M seek=1 if={str(rootfs)} of={disk_path}", shell=True)
ptuuid = check_output(
f"blkid -s PTUUID -o value {disk_path}", shell=True, encoding="ascii"
).strip()
diff --git a/tests/host_tools/network.py b/tests/host_tools/network.py
index e1c53020fd0..7877b914d28 100644
--- a/tests/host_tools/network.py
+++ b/tests/host_tools/network.py
@@ -5,6 +5,7 @@
import ipaddress
import random
import string
+import subprocess
from dataclasses import dataclass, field
from pathlib import Path
@@ -67,9 +68,14 @@ def __init__(self, netns, ssh_key: Path, host, user, *, on_error=None):
self._on_error = on_error
+ @property
+ def user_host(self):
+ """remote address for in SSH format @"""
+ return f"{self.user}@{self.host}"
+
def remote_path(self, path):
"""Convert a path to remote"""
- return f"{self.user}@{self.host}:{path}"
+ return f"{self.user_host}:{path}"
def _scp(self, path1, path2, options):
"""Copy files to/from the VM using scp."""
@@ -111,21 +117,12 @@ def run(self, cmd_string, timeout=None, *, check=False, debug=False):
If `debug` is set, pass `-vvv` to `ssh`. Note that this will clobber stderr.
"""
- command = [
- "ssh",
- *self.options,
- f"{self.user}@{self.host}",
- cmd_string,
- ]
+ command = ["ssh", *self.options, self.user_host, cmd_string]
if debug:
command.insert(1, "-vvv")
- return self._exec(
- command,
- timeout,
- check=check,
- )
+ return self._exec(command, timeout, check=check)
def check_output(self, cmd_string, timeout=None, *, debug=False):
"""Same as `run`, but raises an exception on non-zero return code of remote command"""
@@ -144,6 +141,27 @@ def _exec(self, cmd, timeout=None, check=False):
raise
+ # pylint:disable=invalid-name
+ def Popen(
+ self,
+ cmd: str,
+ stdin=subprocess.DEVNULL,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ **kwargs,
+ ) -> subprocess.Popen:
+ """Execute the command in the guest and return a Popen object.
+
+ pop = uvm.ssh.Popen("while true; do echo $(date -Is) $RANDOM; sleep 1; done")
+ pop.stdout.read(16)
+ """
+ cmd = ["ssh", *self.options, self.user_host, cmd]
+ if self.netns is not None:
+ cmd = ["ip", "netns", "exec", self.netns] + cmd
+ return subprocess.Popen(
+ cmd, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs
+ )
+
def mac_from_ip(ip_address):
"""Create a MAC address based on the provided IP.
diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py
index 5aebe7b5265..27366529c39 100644
--- a/tests/integration_tests/functional/test_api.py
+++ b/tests/integration_tests/functional/test_api.py
@@ -895,7 +895,7 @@ def _drive_patch(test_microvm):
"is_root_device": True,
"cache_type": "Unsafe",
"is_read_only": True,
- "path_on_host": "/ubuntu-22.04.squashfs",
+ "path_on_host": "/" + test_microvm.rootfs_file.name,
"rate_limiter": None,
"io_engine": "Sync",
"socket": None,
@@ -1226,7 +1226,7 @@ def test_get_full_config(uvm_plain):
"is_root_device": True,
"cache_type": "Unsafe",
"is_read_only": True,
- "path_on_host": "/ubuntu-22.04.squashfs",
+ "path_on_host": "/" + test_microvm.rootfs_file.name,
"rate_limiter": None,
"io_engine": "Sync",
"socket": None,
diff --git a/tests/integration_tests/functional/test_balloon.py b/tests/integration_tests/functional/test_balloon.py
index 8d7973db273..ee750dcac7d 100644
--- a/tests/integration_tests/functional/test_balloon.py
+++ b/tests/integration_tests/functional/test_balloon.py
@@ -200,10 +200,10 @@ def test_deflate_on_oom(uvm_plain_any, deflate_on_oom):
# We get an initial reading of the RSS, then calculate the amount
# we need to inflate the balloon with by subtracting it from the
- # VM size and adding an offset of 10 MiB in order to make sure we
+ # VM size and adding an offset of 50 MiB in order to make sure we
# get a lower reading than the initial one.
initial_rss = get_stable_rss_mem_by_pid(firecracker_pid)
- inflate_size = 256 - int(initial_rss / 1024) + 10
+ inflate_size = 256 - (int(initial_rss / 1024) + 50)
# Inflate the balloon
test_microvm.api.balloon.patch(amount_mib=inflate_size)
@@ -213,7 +213,7 @@ def test_deflate_on_oom(uvm_plain_any, deflate_on_oom):
# Check that using memory leads to the balloon device automatically
# deflate (or not).
balloon_size_before = test_microvm.api.balloon_stats.get().json()["actual_mib"]
- make_guest_dirty_memory(test_microvm.ssh, 64)
+ make_guest_dirty_memory(test_microvm.ssh, 128)
balloon_size_after = test_microvm.api.balloon_stats.get().json()["actual_mib"]
print(f"size before: {balloon_size_before} size after: {balloon_size_after}")
diff --git a/tests/integration_tests/functional/test_cmd_line_parameters.py b/tests/integration_tests/functional/test_cmd_line_parameters.py
index 3de378a3141..25e47a50e17 100644
--- a/tests/integration_tests/functional/test_cmd_line_parameters.py
+++ b/tests/integration_tests/functional/test_cmd_line_parameters.py
@@ -5,7 +5,6 @@
import subprocess
from pathlib import Path
-import packaging.version
import pytest
from framework.utils import check_output
@@ -22,14 +21,6 @@ def test_describe_snapshot_all_versions(
snapshot state file.
"""
- # TODO: remove this check once all versions prior to 1.6.0 go out of support.
- if packaging.version.parse(firecracker_release.version) < packaging.version.parse(
- "1.7.0"
- ):
- pytest.skip(
- "We can't parse snapshot files created from Firecracker with version < 1.7.0."
- )
-
target_version = firecracker_release.snapshot_version
vm = microvm_factory.build(
guest_kernel,
diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py
index a1066da21a5..8357f54b568 100644
--- a/tests/integration_tests/functional/test_cpu_features_aarch64.py
+++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py
@@ -2,13 +2,16 @@
# SPDX-License-Identifier: Apache-2.0
"""Tests for the CPU features for aarch64."""
+import os
import platform
import re
import pytest
import framework.utils_cpuid as cpuid_utils
-from framework.utils_cpuid import CpuModel
+from framework import utils
+from framework.properties import global_props
+from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel
PLATFORM = platform.machine()
@@ -48,7 +51,7 @@ def _check_cpu_features_arm(test_microvm, guest_kv, template_name=None):
case CpuModel.ARM_NEOVERSE_V1, _, None:
expected_cpu_features = DEFAULT_G3_FEATURES_5_10
- _, stdout, _ = test_microvm.ssh.check_output(r"lscpu |grep -oP '^Flags:\s+\K.+'")
+ _, stdout, _ = test_microvm.ssh.check_output(CPU_FEATURES_CMD)
flags = set(stdout.strip().split(" "))
assert flags == expected_cpu_features
@@ -67,12 +70,90 @@ def get_cpu_template_dir(cpu_template):
PLATFORM != "aarch64",
reason="This is aarch64 specific test.",
)
-def test_default_cpu_features(microvm_factory, guest_kernel, rootfs_ubuntu_22):
+def test_host_vs_guest_cpu_features_aarch64(uvm_nano):
+ """Check CPU features host vs guest"""
+
+ vm = uvm_nano
+ vm.add_net_iface()
+ vm.start()
+ host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.strip().split(" "))
+ guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.strip().split(" "))
+
+ cpu_model = cpuid_utils.get_cpu_model_name()
+ match cpu_model:
+ case CpuModel.ARM_NEOVERSE_N1:
+ expected_guest_minus_host = set()
+ expected_host_minus_guest = set()
+
+ # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since
+ # they have an errata whereby an MSR to the SSBS special-purpose register does not
+ # affect subsequent speculative instructions, permitting speculative store bypassing for
+ # a window of time.
+ # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641
+ #
+ # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test
+ # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it.
+ host_has_ssbs = global_props.host_os not in {
+ "amzn2",
+ "amzn2023",
+ } and global_props.host_linux_version_tpl < (6, 11)
+ guest_has_ssbs = vm.guest_kernel_version < (6, 11)
+
+ if host_has_ssbs and not guest_has_ssbs:
+ expected_host_minus_guest |= {"ssbs"}
+ if not host_has_ssbs and guest_has_ssbs:
+ expected_guest_minus_host |= {"ssbs"}
+
+ assert host_feats - guest_feats == expected_host_minus_guest
+ assert guest_feats - host_feats == expected_guest_minus_host
+ case CpuModel.ARM_NEOVERSE_V1:
+ expected_guest_minus_host = set()
+ # KVM does not enable PAC or SVE features by default
+ # and Firecracker does not enable them either.
+ expected_host_minus_guest = {
+ "paca",
+ "pacg",
+ "sve",
+ "svebf16",
+ "svei8mm",
+ }
+
+ # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since
+ # they have an errata whereby an MSR to the SSBS special-purpose register does not
+ # affect subsequent speculative instructions, permitting speculative store bypassing for
+ # a window of time.
+ # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641
+ #
+ # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test
+ # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it.
+ host_has_ssbs = global_props.host_os not in {
+ "amzn2",
+ "amzn2023",
+ } and global_props.host_linux_version_tpl < (6, 11)
+ guest_has_ssbs = vm.guest_kernel_version < (6, 11)
+
+ if host_has_ssbs and not guest_has_ssbs:
+ expected_host_minus_guest |= {"ssbs"}
+ if not host_has_ssbs and guest_has_ssbs:
+ expected_guest_minus_host |= {"ssbs"}
+
+ assert host_feats - guest_feats == expected_host_minus_guest
+ assert guest_feats - host_feats == expected_guest_minus_host
+ case _:
+ if os.environ.get("BUILDKITE") is not None:
+ assert False, f"Cpu model {cpu_model} is not supported"
+
+
+@pytest.mark.skipif(
+ PLATFORM != "aarch64",
+ reason="This is aarch64 specific test.",
+)
+def test_default_cpu_features(microvm_factory, guest_kernel, rootfs):
"""
Check the CPU features for a microvm with the specified config.
"""
- vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False)
+ vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
vm.spawn()
vm.basic_config()
vm.add_net_iface()
@@ -86,13 +167,13 @@ def test_default_cpu_features(microvm_factory, guest_kernel, rootfs_ubuntu_22):
reason="This is aarch64 specific test.",
)
def test_cpu_features_with_static_template(
- microvm_factory, guest_kernel, rootfs_ubuntu_22, cpu_template
+ microvm_factory, guest_kernel, rootfs, cpu_template
):
"""
Check the CPU features for a microvm with the specified config.
"""
- vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False)
+ vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
vm.spawn()
vm.basic_config(cpu_template=cpu_template)
vm.add_net_iface()
@@ -114,13 +195,13 @@ def test_cpu_features_with_static_template(
reason="This is aarch64 specific test.",
)
def test_cpu_features_with_custom_template(
- microvm_factory, guest_kernel, rootfs_ubuntu_22, custom_cpu_template
+ microvm_factory, guest_kernel, rootfs, custom_cpu_template
):
"""
Check the CPU features for a microvm with the specified config.
"""
- vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False)
+ vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
vm.spawn()
vm.basic_config()
vm.api.cpu_config.put(**custom_cpu_template["template"])
diff --git a/tests/integration_tests/functional/test_cpu_features.py b/tests/integration_tests/functional/test_cpu_features_x86_64.py
similarity index 78%
rename from tests/integration_tests/functional/test_cpu_features.py
rename to tests/integration_tests/functional/test_cpu_features_x86_64.py
index 225bec620eb..23818ddc6b1 100644
--- a/tests/integration_tests/functional/test_cpu_features.py
+++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py
@@ -22,6 +22,7 @@
from framework.defs import SUPPORTED_HOST_KERNELS
from framework.properties import global_props
from framework.utils_cpu_templates import SUPPORTED_CPU_TEMPLATES
+from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel
PLATFORM = platform.machine()
UNSUPPORTED_HOST_KERNEL = (
@@ -203,6 +204,293 @@ def test_brand_string(uvm_plain_any):
assert False
+@pytest.mark.skipif(
+ PLATFORM != "x86_64",
+ reason="This is x86_64 specific test.",
+)
+def test_host_vs_guest_cpu_features_x86_64(uvm_nano):
+ """Check CPU features host vs guest"""
+
+ vm = uvm_nano
+ vm.add_net_iface()
+ vm.start()
+ host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.strip().split(" "))
+ guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.strip().split(" "))
+
+ cpu_model = cpuid_utils.get_cpu_codename()
+ match cpu_model:
+ case CpuModel.AMD_MILAN:
+ host_guest_diff_5_10 = {
+ "amd_ppin",
+ "aperfmperf",
+ "bpext",
+ "cat_l3",
+ "cdp_l3",
+ "cpb",
+ "cqm",
+ "cqm_llc",
+ "cqm_mbm_local",
+ "cqm_mbm_total",
+ "cqm_occup_llc",
+ "decodeassists",
+ "extapic",
+ "extd_apicid",
+ "flushbyasid",
+ "hw_pstate",
+ "ibs",
+ "irperf",
+ "lbrv",
+ "mba",
+ "monitor",
+ "mwaitx",
+ "overflow_recov",
+ "pausefilter",
+ "perfctr_llc",
+ "perfctr_nb",
+ "pfthreshold",
+ "rdpru",
+ "rdt_a",
+ "sev",
+ "sev_es",
+ "skinit",
+ "smca",
+ "sme",
+ "succor",
+ "svm_lock",
+ "tce",
+ "tsc_scale",
+ "v_vmsave_vmload",
+ "vgif",
+ "vmcb_clean",
+ "wdt",
+ }
+
+ host_guest_diff_6_1 = host_guest_diff_5_10 - {
+ "lbrv",
+ "pausefilter",
+ "pfthreshold",
+ "sme",
+ "tsc_scale",
+ "v_vmsave_vmload",
+ "vgif",
+ "vmcb_clean",
+ } | {"brs", "rapl", "v_spec_ctrl"}
+
+ if global_props.host_linux_version_tpl < (6, 1):
+ assert host_feats - guest_feats == host_guest_diff_5_10
+ else:
+ assert host_feats - guest_feats == host_guest_diff_6_1
+
+ assert guest_feats - host_feats == {
+ "hypervisor",
+ "tsc_adjust",
+ "tsc_deadline_timer",
+ "tsc_known_freq",
+ }
+ case CpuModel.INTEL_SKYLAKE:
+ assert host_feats - guest_feats == {
+ "acpi",
+ "aperfmperf",
+ "arch_perfmon",
+ "art",
+ "bts",
+ "cat_l3",
+ "cdp_l3",
+ "cqm",
+ "cqm_llc",
+ "cqm_mbm_local",
+ "cqm_mbm_total",
+ "cqm_occup_llc",
+ "dca",
+ "ds_cpl",
+ "dtes64",
+ "dtherm",
+ "dts",
+ "epb",
+ "ept",
+ "ept_ad",
+ "est",
+ "flexpriority",
+ "flush_l1d",
+ "hwp",
+ "hwp_act_window",
+ "hwp_epp",
+ "hwp_pkg_req",
+ "ida",
+ "intel_ppin",
+ "intel_pt",
+ "mba",
+ "monitor",
+ "pbe",
+ "pdcm",
+ "pebs",
+ "pln",
+ "pts",
+ "rdt_a",
+ "sdbg",
+ "smx",
+ "tm",
+ "tm2",
+ "tpr_shadow",
+ "vmx",
+ "vnmi",
+ "vpid",
+ "xtpr",
+ }
+ assert guest_feats - host_feats == {
+ "hypervisor",
+ "tsc_known_freq",
+ "umip",
+ }
+ case CpuModel.INTEL_CASCADELAKE:
+ expected_host_minus_guest = {
+ "acpi",
+ "aperfmperf",
+ "arch_perfmon",
+ "art",
+ "bts",
+ "cat_l3",
+ "cdp_l3",
+ "cqm",
+ "cqm_llc",
+ "cqm_mbm_local",
+ "cqm_mbm_total",
+ "cqm_occup_llc",
+ "dca",
+ "ds_cpl",
+ "dtes64",
+ "dtherm",
+ "dts",
+ "epb",
+ "ept",
+ "ept_ad",
+ "est",
+ "flexpriority",
+ "flush_l1d",
+ "hwp",
+ "hwp_act_window",
+ "hwp_epp",
+ "hwp_pkg_req",
+ "ida",
+ "intel_ppin",
+ "intel_pt",
+ "mba",
+ "monitor",
+ "pbe",
+ "pdcm",
+ "pebs",
+ "pln",
+ "pts",
+ "rdt_a",
+ "sdbg",
+ "smx",
+ "tm",
+ "tm2",
+ "tpr_shadow",
+ "vmx",
+ "vnmi",
+ "vpid",
+ "xtpr",
+ }
+ expected_guest_minus_host = {
+ "hypervisor",
+ "tsc_known_freq",
+ "umip",
+ }
+
+ # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests.
+ # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e
+ #
+ # Our test ubuntu host kernel is v6.8 and has the commit.
+ if global_props.host_linux_version_tpl >= (6, 4):
+ expected_host_minus_guest -= {"flush_l1d"}
+
+ # Linux kernel v6.6+ drops the "invpcid_single" synthetic feature bit.
+ # https://github.com/torvalds/linux/commit/54e3d9434ef61b97fd3263c141b928dc5635e50d
+ #
+ # Our test ubuntu host kernel is v6.8 and has the commit.
+ host_has_invpcid_single = global_props.host_linux_version_tpl < (6, 6)
+ guest_has_invpcid_single = vm.guest_kernel_version < (6, 6)
+ if host_has_invpcid_single and not guest_has_invpcid_single:
+ expected_host_minus_guest |= {"invpcid_single"}
+ if not host_has_invpcid_single and guest_has_invpcid_single:
+ expected_guest_minus_host |= {"invpcid_single"}
+
+ assert host_feats - guest_feats == expected_host_minus_guest
+ assert guest_feats - host_feats == expected_guest_minus_host
+ case CpuModel.INTEL_ICELAKE:
+ host_guest_diff_5_10 = {
+ "dtes64",
+ "hwp_act_window",
+ "pdcm",
+ "acpi",
+ "aperfmperf",
+ "arch_perfmon",
+ "art",
+ "bts",
+ "cat_l3",
+ "cqm",
+ "cqm_llc",
+ "cqm_mbm_local",
+ "cqm_mbm_total",
+ "cqm_occup_llc",
+ "dca",
+ "ds_cpl",
+ "dtherm",
+ "dts",
+ "epb",
+ "ept",
+ "ept_ad",
+ "est",
+ "flexpriority",
+ "flush_l1d",
+ "hwp",
+ "hwp_epp",
+ "hwp_pkg_req",
+ "ida",
+ "intel_ppin",
+ "intel_pt",
+ "mba",
+ "monitor",
+ "pbe",
+ "pconfig",
+ "pebs",
+ "pln",
+ "pts",
+ "rdt_a",
+ "sdbg",
+ "smx",
+ "split_lock_detect",
+ "tm",
+ "tm2",
+ "tme",
+ "tpr_shadow",
+ "vmx",
+ "vnmi",
+ "vpid",
+ "xtpr",
+ }
+ host_guest_diff_6_1 = host_guest_diff_5_10 - {
+ "bts",
+ "dtes64",
+ "dts",
+ "pebs",
+ }
+
+ if global_props.host_linux_version_tpl < (6, 1):
+ assert host_feats - guest_feats == host_guest_diff_5_10
+ else:
+ assert host_feats - guest_feats == host_guest_diff_6_1
+
+ assert guest_feats - host_feats == {
+ "hypervisor",
+ "tsc_known_freq",
+ }
+ case _:
+ if os.environ.get("BUILDKITE") is not None:
+ assert False, f"Cpu model {cpu_model} is not supported"
+
+
# From the `Intel® 64 Architecture x2APIC Specification`
# (https://courses.cs.washington.edu/courses/cse451/24wi/documentation/x2apic.pdf):
# > The X2APIC MSRs cannot to be loaded and stored on VMX transitions. A VMX transition fails
@@ -272,7 +560,7 @@ def msr_cpu_template_fxt(request):
@pytest.mark.timeout(900)
@pytest.mark.nonci
def test_cpu_rdmsr(
- microvm_factory, msr_cpu_template, guest_kernel, rootfs_ubuntu_22, results_dir
+ microvm_factory, msr_cpu_template, guest_kernel, rootfs, results_dir
):
"""
Test MSRs that are available to the guest.
@@ -307,7 +595,7 @@ def test_cpu_rdmsr(
"""
vcpus, guest_mem_mib = 1, 1024
- vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False)
+ vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
vm.spawn()
vm.add_net_iface()
vm.basic_config(
@@ -376,9 +664,7 @@ def dump_msr_state_to_file(dump_fname, ssh_conn, shared_names):
)
@pytest.mark.timeout(900)
@pytest.mark.nonci
-def test_cpu_wrmsr_snapshot(
- microvm_factory, guest_kernel, rootfs_ubuntu_22, msr_cpu_template
-):
+def test_cpu_wrmsr_snapshot(microvm_factory, guest_kernel, rootfs, msr_cpu_template):
"""
This is the first part of the test verifying
that MSRs retain their values after restoring from a snapshot.
@@ -398,7 +684,7 @@ def test_cpu_wrmsr_snapshot(
shared_names = SNAPSHOT_RESTORE_SHARED_NAMES
vcpus, guest_mem_mib = 1, 1024
- vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False)
+ vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
vm.spawn()
vm.add_net_iface()
vm.basic_config(
@@ -533,9 +819,7 @@ def dump_cpuid_to_file(dump_fname, ssh_conn):
)
@pytest.mark.timeout(900)
@pytest.mark.nonci
-def test_cpu_cpuid_snapshot(
- microvm_factory, guest_kernel, rootfs_ubuntu_22, msr_cpu_template
-):
+def test_cpu_cpuid_snapshot(microvm_factory, guest_kernel, rootfs, msr_cpu_template):
"""
This is the first part of the test verifying
that CPUID remains the same after restoring from a snapshot.
@@ -551,7 +835,7 @@ def test_cpu_cpuid_snapshot(
vm = microvm_factory.build(
kernel=guest_kernel,
- rootfs=rootfs_ubuntu_22,
+ rootfs=rootfs,
)
vm.spawn()
vm.add_net_iface()
@@ -927,9 +1211,9 @@ def check_enabled_features(test_microvm, cpu_template):
"enhanced REP MOVSB/STOSB": "true",
"SMAP: supervisor mode access prevention": "true",
# xsave_0xd_0
- "XCR0 supported: x87 state": "true",
- "XCR0 supported: SSE state": "true",
- "XCR0 supported: AVX state": "true",
+ "x87 state": "true",
+ "SSE state": "true",
+ "AVX state": "true",
# xsave_0xd_1
"XSAVEOPT instruction": "true",
# extended_080000001_edx
diff --git a/tests/integration_tests/functional/test_drive_vhost_user.py b/tests/integration_tests/functional/test_drive_vhost_user.py
index 31a11a75661..79cc41b0f3a 100644
--- a/tests/integration_tests/functional/test_drive_vhost_user.py
+++ b/tests/integration_tests/functional/test_drive_vhost_user.py
@@ -34,7 +34,7 @@ def _check_drives(test_microvm, assert_dict, keys_array):
assert blockdev_out_line_cols[col] == assert_dict[key]
-def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_22):
+def test_vhost_user_block(microvm_factory, guest_kernel, rootfs):
"""
This test simply tries to boot a VM with
vhost-user-block as a root device.
@@ -44,13 +44,11 @@ def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_22):
# We need to setup ssh keys manually because we did not specify rootfs
# in microvm_factory.build method
- ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa")
+ ssh_key = rootfs.with_suffix(".id_rsa")
vm.ssh_key = ssh_key
vm.spawn()
vm.basic_config(add_root_device=False)
- vm.add_vhost_user_drive(
- "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True
- )
+ vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True)
vm.add_net_iface()
vhost_user_block_metrics = FcDeviceMetrics(
"vhost_user_block", 1, aggr_supported=False
@@ -67,7 +65,7 @@ def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_22):
vhost_user_block_metrics.validate(vm)
-def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubuntu_22):
+def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs):
"""
This test simply tries to boot a VM with
vhost-user-block as a root device.
@@ -78,14 +76,14 @@ def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubunt
# We need to setup ssh keys manually because we did not specify rootfs
# in microvm_factory.build method
- ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa")
+ ssh_key = rootfs.with_suffix(".id_rsa")
vm.ssh_key = ssh_key
vm.spawn()
vm.basic_config(add_root_device=False)
# Create a rw rootfs file that is unique to the microVM
rootfs_rw = Path(vm.chroot()) / "rootfs"
- shutil.copy(rootfs_ubuntu_22, rootfs_rw)
+ shutil.copy(rootfs, rootfs_rw)
vm.add_vhost_user_drive("rootfs", rootfs_rw, is_root_device=True)
vm.add_net_iface()
@@ -100,7 +98,7 @@ def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubunt
_check_drives(vm, assert_dict, assert_dict.keys())
-def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubuntu_22):
+def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs):
"""
Test that even if backend is killed, Firecracker is still responsive.
"""
@@ -109,13 +107,11 @@ def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubunt
# We need to set up ssh keys manually because we did not specify rootfs
# in microvm_factory.build method
- ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa")
+ ssh_key = rootfs.with_suffix(".id_rsa")
vm.ssh_key = ssh_key
vm.spawn()
vm.basic_config(add_root_device=False)
- vm.add_vhost_user_drive(
- "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True
- )
+ vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True)
vm.add_net_iface()
vm.start()
@@ -127,7 +123,7 @@ def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubunt
_config = vm.api.vm_config.get().json()
-def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22):
+def test_device_ordering(microvm_factory, guest_kernel, rootfs):
"""
Verify device ordering.
@@ -139,7 +135,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22):
# We need to setup ssh keys manually because we did not specify rootfs
# in microvm_factory.build method
- ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa")
+ ssh_key = rootfs.with_suffix(".id_rsa")
vm.ssh_key = ssh_key
vm.spawn()
vm.basic_config(add_root_device=False)
@@ -150,9 +146,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22):
vm.add_drive("scratch1", fs1.path)
# Adding second block device (rootfs)
- vm.add_vhost_user_drive(
- "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True
- )
+ vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True)
# Adding third block device.
fs2 = drive_tools.FilesystemFile(os.path.join(vm.fsfiles, "scratch2"), size=512)
@@ -160,7 +154,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22):
# Create a rw rootfs file that is unique to the microVM
rootfs_rw = Path(vm.chroot()) / "rootfs"
- shutil.copy(rootfs_ubuntu_22, rootfs_rw)
+ shutil.copy(rootfs, rootfs_rw)
# Adding forth block device.
vm.add_vhost_user_drive("dummy_rootfs", rootfs_rw)
@@ -171,7 +165,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22):
)
vm.start()
- rootfs_size = rootfs_ubuntu_22.stat().st_size
+ rootfs_size = rootfs.stat().st_size
# The devices were added in this order: fs1, rootfs, fs2. fs3
# However, the rootfs is the root device and goes first,
@@ -203,7 +197,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22):
def test_partuuid_boot(
microvm_factory,
guest_kernel,
- rootfs_ubuntu_22,
+ rootfs,
):
"""
Test the output reported by blockdev when booting with PARTUUID.
@@ -213,15 +207,13 @@ def test_partuuid_boot(
# We need to setup ssh keys manually because we did not specify rootfs
# in microvm_factory.build method
- ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa")
+ ssh_key = rootfs.with_suffix(".id_rsa")
vm.ssh_key = ssh_key
vm.spawn()
vm.basic_config(add_root_device=False)
# Create a rootfs with partuuid unique to this microVM
- partuuid, disk_path = partuuid_and_disk_path(
- rootfs_ubuntu_22, Path(vm.chroot()) / "disk.img"
- )
+ partuuid, disk_path = partuuid_and_disk_path(rootfs, Path(vm.chroot()) / "disk.img")
vm.add_vhost_user_drive(
"1", disk_path, is_root_device=True, partuuid=partuuid, is_read_only=True
@@ -238,7 +230,7 @@ def test_partuuid_boot(
_check_drives(vm, assert_dict, assert_dict.keys())
-def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_22):
+def test_partuuid_update(microvm_factory, guest_kernel, rootfs):
"""
Test successful switching from PARTUUID boot to /dev/vda boot.
"""
@@ -247,7 +239,7 @@ def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_22):
# We need to setup ssh keys manually because we did not specify rootfs
# in microvm_factory.build method
- ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa")
+ ssh_key = rootfs.with_suffix(".id_rsa")
vm.ssh_key = ssh_key
vm.spawn()
vm.basic_config(add_root_device=False)
@@ -256,16 +248,14 @@ def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_22):
# Add the root block device specified through PARTUUID.
vm.add_vhost_user_drive(
"rootfs",
- rootfs_ubuntu_22,
+ rootfs,
is_root_device=True,
partuuid="0eaa91a0-01",
is_read_only=True,
)
# Adding a drive with the same ID creates another backend with another socket.
- vm.add_vhost_user_drive(
- "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True
- )
+ vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True)
vhost_user_block_metrics = FcDeviceMetrics(
"vhost_user_block", 1, aggr_supported=False
diff --git a/tests/integration_tests/functional/test_drive_virtio.py b/tests/integration_tests/functional/test_drive_virtio.py
index dbebefa11a1..9c61ead56a9 100644
--- a/tests/integration_tests/functional/test_drive_virtio.py
+++ b/tests/integration_tests/functional/test_drive_virtio.py
@@ -14,12 +14,12 @@
@pytest.fixture
-def partuuid_and_disk_path_tmpfs(rootfs_ubuntu_22, tmp_path):
+def partuuid_and_disk_path_tmpfs(rootfs, tmp_path):
"""
We create a new file in tmpfs, get its partuuid and use it as a rootfs.
"""
disk_path = tmp_path / "disk.img"
- yield partuuid_and_disk_path(rootfs_ubuntu_22, disk_path)
+ yield partuuid_and_disk_path(rootfs, disk_path)
disk_path.unlink()
diff --git a/tests/integration_tests/functional/test_kernel_cmdline.py b/tests/integration_tests/functional/test_kernel_cmdline.py
index 14e369790f1..9707eb8a92c 100644
--- a/tests/integration_tests/functional/test_kernel_cmdline.py
+++ b/tests/integration_tests/functional/test_kernel_cmdline.py
@@ -29,4 +29,4 @@ def test_init_params(uvm_plain):
serial = Serial(vm)
serial.open()
# If the string does not show up, the test will fail.
- serial.rx(token="Ubuntu 22.04")
+ serial.rx(token="Ubuntu 24.04")
diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py
index 12980c727b2..a804b8f90a8 100644
--- a/tests/integration_tests/functional/test_net.py
+++ b/tests/integration_tests/functional/test_net.py
@@ -10,7 +10,11 @@
from framework import utils
# The iperf version to run this tests with
-IPERF_BINARY = "iperf3"
+IPERF_BINARY_GUEST = "iperf3"
+# We are using iperf3-vsock instead of a regular iperf3,
+# because iperf3 3.16+ crashes on aarch64 sometimes
+# when running this test.
+IPERF_BINARY_HOST = "iperf3-vsock"
def test_high_ingress_traffic(uvm_plain_any):
@@ -33,15 +37,15 @@ def test_high_ingress_traffic(uvm_plain_any):
test_microvm.start()
# Start iperf3 server on the guest.
- test_microvm.ssh.run("{} -sD\n".format(IPERF_BINARY))
+ test_microvm.ssh.check_output("{} -sD\n".format(IPERF_BINARY_GUEST))
time.sleep(1)
# Start iperf3 client on the host. Send 1Gbps UDP traffic.
# If the net device breaks, iperf will freeze. We have to use a timeout.
- utils.run_cmd(
- "timeout 30 {} {} -c {} -u -V -b 1000000000 -t 30".format(
+ utils.check_output(
+ "timeout 31 {} {} -c {} -u -V -b 1000000000 -t 30".format(
test_microvm.netns.cmd_prefix(),
- IPERF_BINARY,
+ IPERF_BINARY_HOST,
guest_ip,
),
)
@@ -95,7 +99,7 @@ def run_udp_offload_test(vm):
# Start a UDP server in the guest
# vm.ssh.check_output(f"nohup socat UDP-LISTEN:{port} - > {out_filename} &")
vm.ssh.check_output(
- f"nohup socat UDP-LISTEN:{port} OPEN:{out_filename},creat > /dev/null 2>&1 &"
+ f"nohup socat UDP4-LISTEN:{port} OPEN:{out_filename},creat > /dev/null 2>&1 &"
)
# Try to send a UDP message from host with UDP offload enabled
@@ -123,11 +127,11 @@ def test_tap_offload_booted(uvm_plain_any):
run_udp_offload_test(vm)
-def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs_ubuntu_22):
+def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs):
"""
Verify that tap offload features are configured for a restored VM.
"""
- src = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False)
+ src = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
src.spawn()
src.basic_config()
src.add_net_iface()
diff --git a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py
index 812e706b926..5584cfceac8 100644
--- a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py
+++ b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py
@@ -25,14 +25,14 @@ def mount_tmpfs_small(worker_id):
def test_diff_snapshot_works_after_error(
- microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, mount_tmpfs_small
+ microvm_factory, guest_kernel_linux_5_10, rootfs, mount_tmpfs_small
):
"""
Test that if a partial snapshot errors it will work after and not lose data
"""
uvm = microvm_factory.build(
guest_kernel_linux_5_10,
- rootfs_ubuntu_22,
+ rootfs,
jailer_kwargs={"chroot_base": mount_tmpfs_small},
)
diff --git a/tests/integration_tests/functional/test_snapshot_phase1.py b/tests/integration_tests/functional/test_snapshot_phase1.py
new file mode 100644
index 00000000000..7436c19d875
--- /dev/null
+++ b/tests/integration_tests/functional/test_snapshot_phase1.py
@@ -0,0 +1,108 @@
+# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+
+"""
+Creates snapshots for other tests like test_snapshot_restore_cross_kernel.py
+"""
+
+import json
+import platform
+import re
+
+import pytest
+
+from framework.utils import (
+ configure_mmds,
+ generate_mmds_get_request,
+ generate_mmds_session_token,
+)
+
+if platform.machine() != "x86_64":
+ pytestmark = pytest.mark.skip("only x86_64 architecture supported")
+
+# Default IPv4 address to route MMDS requests.
+IPV4_ADDRESS = "169.254.169.254"
+NET_IFACE_FOR_MMDS = "eth3"
+
+
+@pytest.mark.nonci
+def test_snapshot_phase1(
+ microvm_factory, guest_kernel, rootfs, cpu_template_any, results_dir
+):
+ """Create a snapshot and save it to disk"""
+
+ vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
+ vm.spawn(log_level="Info")
+ vm.add_net_iface()
+
+ static_cpu_template = None
+ cpu_template_name = "None"
+ if isinstance(cpu_template_any, str):
+ static_cpu_template = cpu_template_any
+ cpu_template_name = f"static_{cpu_template_any}"
+ elif isinstance(cpu_template_any, dict):
+ vm.api.cpu_config.put(**cpu_template_any["template"])
+ cpu_template_name = f"custom_{cpu_template_any['name']}"
+ vm.basic_config(
+ vcpu_count=2,
+ mem_size_mib=512,
+ cpu_template=static_cpu_template,
+ )
+
+ guest_kernel_version = re.search("vmlinux-(.*)", vm.kernel_file.name)
+ snapshot_artifacts_dir = (
+ results_dir
+ / f"{guest_kernel_version.group(1)}_{cpu_template_name}_guest_snapshot"
+ )
+
+ # Add 4 network devices
+ for i in range(4):
+ vm.add_net_iface()
+ # Add a vsock device
+ vm.api.vsock.put(vsock_id="vsock0", guest_cid=3, uds_path="/v.sock")
+ # Add MMDS
+ configure_mmds(vm, ["eth3"], version="V2")
+ # Add a memory balloon.
+ vm.api.balloon.put(amount_mib=0, deflate_on_oom=True, stats_polling_interval_s=1)
+
+ vm.start()
+
+ # Populate MMDS.
+ data_store = {
+ "latest": {
+ "meta-data": {
+ "ami-id": "ami-12345678",
+ "reservation-id": "r-fea54097",
+ "local-hostname": "ip-10-251-50-12.ec2.internal",
+ "public-hostname": "ec2-203-0-113-25.compute-1.amazonaws.com",
+ }
+ }
+ }
+
+ # MMDS should be empty.
+ assert vm.api.mmds.get().json() == {}
+ # Populate MMDS with data.
+ vm.api.mmds.put(**data_store)
+ # Ensure data is persistent inside the data store.
+ assert vm.api.mmds.get().json() == data_store
+
+ # Iterate and validate connectivity on all ifaces after boot.
+ for i in range(4):
+ exit_code, _, _ = vm.ssh_iface(i).run("sync")
+ assert exit_code == 0
+
+ # Validate MMDS.
+ # Configure interface to route MMDS requests
+ vm.ssh.check_output(f"ip route add {IPV4_ADDRESS} dev {NET_IFACE_FOR_MMDS}")
+
+ # Fetch metadata to ensure MMDS is accessible.
+ token = generate_mmds_session_token(vm.ssh, IPV4_ADDRESS, token_ttl=60)
+ cmd = generate_mmds_get_request(IPV4_ADDRESS, token=token)
+ _, stdout, _ = vm.ssh.run(cmd)
+ assert json.loads(stdout) == data_store
+
+ # Copy snapshot files to be published to S3 for the 2nd part of the test
+ # Create snapshot artifacts directory specific for the kernel version used.
+ snapshot = vm.snapshot_full()
+ snapshot_artifacts_dir.mkdir(parents=True)
+ snapshot.save_to(snapshot_artifacts_dir)
diff --git a/tests/integration_tests/functional/test_uffd.py b/tests/integration_tests/functional/test_uffd.py
index 44de52ed2d5..fbb86c4c987 100644
--- a/tests/integration_tests/functional/test_uffd.py
+++ b/tests/integration_tests/functional/test_uffd.py
@@ -14,10 +14,10 @@
@pytest.fixture(scope="function", name="snapshot")
-def snapshot_fxt(microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22):
+def snapshot_fxt(microvm_factory, guest_kernel_linux_5_10, rootfs):
"""Create a snapshot of a microVM."""
- basevm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22)
+ basevm = microvm_factory.build(guest_kernel_linux_5_10, rootfs)
basevm.spawn()
basevm.basic_config(vcpu_count=2, mem_size_mib=256)
basevm.add_net_iface()
diff --git a/tests/integration_tests/performance/test_benchmarks.py b/tests/integration_tests/performance/test_benchmarks.py
index 3a33a1a80bb..6e6541a688d 100644
--- a/tests/integration_tests/performance/test_benchmarks.py
+++ b/tests/integration_tests/performance/test_benchmarks.py
@@ -1,6 +1,7 @@
# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""Optional benchmarks-do-not-regress test"""
+import contextlib
import json
import logging
import platform
@@ -10,7 +11,7 @@
import pytest
from framework import utils
-from framework.ab_test import chdir, git_ab_test
+from framework.ab_test import git_ab_test
from host_tools.cargo_build import cargo
LOGGER = logging.getLogger(__name__)
@@ -32,7 +33,7 @@ def run_criterion(firecracker_checkout: Path, is_a: bool) -> Path:
"""
baseline_name = "a_baseline" if is_a else "b_baseline"
- with chdir(firecracker_checkout):
+ with contextlib.chdir(firecracker_checkout):
# Passing --message-format json to cargo tells it to print its log in a json format. At the end, instead of the
# usual "placed executable <...> at <...>" we'll get a json object with an 'executable' key, from which we
# extract the path to the compiled benchmark binary.
diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py
index 034ee6749a0..8437d78c7d3 100644
--- a/tests/integration_tests/performance/test_huge_pages.py
+++ b/tests/integration_tests/performance/test_huge_pages.py
@@ -70,14 +70,14 @@ def test_hugetlbfs_boot(uvm_plain):
def test_hugetlbfs_snapshot(
- microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, uffd_handler_paths
+ microvm_factory, guest_kernel_linux_5_10, rootfs, uffd_handler_paths
):
"""
Test hugetlbfs snapshot restore via uffd
"""
### Create Snapshot ###
- vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22)
+ vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs)
vm.memory_monitor = None
vm.spawn()
vm.basic_config(huge_pages=HugePagesConfig.HUGETLBFS_2MB, mem_size_mib=128)
@@ -152,7 +152,7 @@ def test_hugetlbfs_diff_snapshot(microvm_factory, uvm_plain, uffd_handler_paths)
def test_ept_violation_count(
microvm_factory,
guest_kernel_linux_5_10,
- rootfs_ubuntu_22,
+ rootfs,
uffd_handler_paths,
metrics,
huge_pages,
@@ -163,7 +163,7 @@ def test_ept_violation_count(
"""
### Create Snapshot ###
- vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22)
+ vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs)
vm.memory_monitor = None
vm.spawn()
vm.basic_config(huge_pages=huge_pages, mem_size_mib=256)
diff --git a/tests/integration_tests/performance/test_vhost_user_metrics.py b/tests/integration_tests/performance/test_vhost_user_metrics.py
index 45fb7a94114..fd20b34a47b 100644
--- a/tests/integration_tests/performance/test_vhost_user_metrics.py
+++ b/tests/integration_tests/performance/test_vhost_user_metrics.py
@@ -11,7 +11,7 @@
@pytest.mark.parametrize("vcpu_count", [1, 2], ids=["1vcpu", "2vcpu"])
def test_vhost_user_block_metrics(
- microvm_factory, guest_kernel_acpi, rootfs_ubuntu_22, vcpu_count, metrics
+ microvm_factory, guest_kernel_acpi, rootfs, vcpu_count, metrics
):
"""
This test tries to boot a VM with vhost-user-block
@@ -28,9 +28,7 @@ def test_vhost_user_block_metrics(
# low->high->low->high and so the numbers are not in monotonic sequence.
new_sizes = [20, 10, 30] # MB
- vm = microvm_factory.build(
- guest_kernel_acpi, rootfs_ubuntu_22, monitor_memory=False
- )
+ vm = microvm_factory.build(guest_kernel_acpi, rootfs, monitor_memory=False)
vm.spawn(log_level="Info")
vm.basic_config(vcpu_count=vcpu_count)
vm.add_net_iface()
diff --git a/tests/integration_tests/security/test_jail.py b/tests/integration_tests/security/test_jail.py
index 68bb220e0c9..ad6a16e48f5 100644
--- a/tests/integration_tests/security/test_jail.py
+++ b/tests/integration_tests/security/test_jail.py
@@ -64,19 +64,14 @@ def test_empty_jailer_id(uvm_plain):
exec_file=test_microvm.fc_binary_path,
)
- # pylint: disable=W0703
- try:
+ # If the exception is not thrown, it means that Firecracker was
+ # started successfully, hence there's a bug in the code due to which
+ # we can set an empty ID.
+ with pytest.raises(
+ ChildProcessError,
+ match=r"Jailer error: Invalid instance ID: Invalid len \(0\); the length must be between 1 and 64",
+ ):
test_microvm.spawn()
- # If the exception is not thrown, it means that Firecracker was
- # started successfully, hence there's a bug in the code due to which
- # we can set an empty ID.
- assert False
- except Exception as err:
- expected_err = (
- "Jailer error: Invalid instance ID: Invalid len (0);"
- " the length must be between 1 and 64"
- )
- assert expected_err in str(err)
def test_exec_file_not_exist(uvm_plain, tmp_path):
diff --git a/tests/integration_tests/security/test_nv.py b/tests/integration_tests/security/test_nv.py
index ce848c6a789..5dd5acb2308 100644
--- a/tests/integration_tests/security/test_nv.py
+++ b/tests/integration_tests/security/test_nv.py
@@ -20,17 +20,15 @@
@pytest.fixture
-def uvm_with_cpu_template(
- microvm_factory, guest_kernel, rootfs_ubuntu_22, cpu_template_any
-):
+def uvm_with_cpu_template(microvm_factory, guest_kernel, rootfs, cpu_template_any):
"""A microvm fixture parametrized with all possible templates"""
- vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22)
+ vm = microvm_factory.build(guest_kernel, rootfs)
vm.spawn()
cpu_template = None
if isinstance(cpu_template_any, str):
cpu_template = cpu_template_any
vm.basic_config(cpu_template=cpu_template)
- if cpu_template is None:
+ if isinstance(cpu_template_any, dict):
vm.api.cpu_config.put(**cpu_template_any["template"])
vm.add_net_iface()
vm.start()
diff --git a/tests/integration_tests/security/test_vulnerabilities.py b/tests/integration_tests/security/test_vulnerabilities.py
index a7faf762acd..fed9dbc96d7 100644
--- a/tests/integration_tests/security/test_vulnerabilities.py
+++ b/tests/integration_tests/security/test_vulnerabilities.py
@@ -11,11 +11,11 @@
import pytest
import requests
+from framework import utils
from framework.ab_test import (
- git_ab_test_guest_command,
- git_ab_test_guest_command_if_pr,
- git_ab_test_host_command_if_pr,
is_pr,
+ precompiled_ab_test_guest_command,
+ precompiled_ab_test_guest_command_if_pr,
set_did_not_grow_comparator,
)
from framework.properties import global_props
@@ -67,13 +67,13 @@ def configure_microvm(
def build_microvm(
microvm_factory,
guest_kernel_linux_5_10,
- rootfs_ubuntu_22,
+ rootfs,
):
"""Fixture returning a factory function for a normal microvm"""
return lambda firecracker=None, jailer=None: configure_microvm(
microvm_factory,
guest_kernel_linux_5_10,
- rootfs_ubuntu_22,
+ rootfs,
firecracker=firecracker,
jailer=jailer,
)
@@ -81,13 +81,13 @@ def build_microvm(
@pytest.fixture
def build_microvm_with_template(
- microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, cpu_template
+ microvm_factory, guest_kernel_linux_5_10, rootfs, cpu_template
):
"""Fixture returning a factory function for microvms with our built-in template"""
return lambda firecracker=None, jailer=None: configure_microvm(
microvm_factory,
guest_kernel_linux_5_10,
- rootfs_ubuntu_22,
+ rootfs,
firecracker=firecracker,
jailer=jailer,
cpu_template=cpu_template,
@@ -96,13 +96,13 @@ def build_microvm_with_template(
@pytest.fixture
def build_microvm_with_custom_template(
- microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, custom_cpu_template
+ microvm_factory, guest_kernel_linux_5_10, rootfs, custom_cpu_template
):
"""Fixture returning a factory function for microvms with custom cpu templates"""
return lambda firecracker=None, jailer=None: configure_microvm(
microvm_factory,
guest_kernel_linux_5_10,
- rootfs_ubuntu_22,
+ rootfs,
firecracker=firecracker,
jailer=jailer,
custom_cpu_template=custom_cpu_template,
@@ -212,20 +212,17 @@ def check_vulnerabilities_on_guest(status):
assert report_guest_vulnerabilities == known_guest_vulnerabilities
+# Nothing can be sensibly tested in a PR context here
+@pytest.mark.skipif(
+ is_pr(), reason="Test depends solely on factors external to GitHub repository"
+)
def test_spectre_meltdown_checker_on_host(spectre_meltdown_checker):
"""
Test with the spectre / meltdown checker on host.
"""
- output = git_ab_test_host_command_if_pr(
- f"sh {spectre_meltdown_checker} --batch json",
- comparator=set_did_not_grow_comparator(
- spectre_meltdown_reported_vulnerablities
- ),
- check_in_nonpr=False,
- )
+ rc, output, _ = utils.run_cmd(f"sh {spectre_meltdown_checker} --batch json")
- # Outside the PR context, checks the return code with some exceptions.
- if output and output.returncode != 0:
+ if output and rc != 0:
report = spectre_meltdown_reported_vulnerablities(output)
expected = {}
assert report == expected, f"Unexpected vulnerabilities: {report} vs {expected}"
@@ -236,7 +233,7 @@ def test_spectre_meltdown_checker_on_guest(spectre_meltdown_checker, build_micro
Test with the spectre / meltdown checker on guest.
"""
- status = git_ab_test_guest_command_if_pr(
+ status = precompiled_ab_test_guest_command_if_pr(
with_checker(build_microvm, spectre_meltdown_checker),
REMOTE_CHECKER_COMMAND,
comparator=set_did_not_grow_comparator(
@@ -254,7 +251,7 @@ def test_spectre_meltdown_checker_on_restored_guest(
"""
Test with the spectre / meltdown checker on a restored guest.
"""
- status = git_ab_test_guest_command_if_pr(
+ status = precompiled_ab_test_guest_command_if_pr(
with_checker(
with_restore(build_microvm, microvm_factory), spectre_meltdown_checker
),
@@ -275,7 +272,7 @@ def test_spectre_meltdown_checker_on_guest_with_template(
Test with the spectre / meltdown checker on guest with CPU template.
"""
- git_ab_test_guest_command_if_pr(
+ precompiled_ab_test_guest_command_if_pr(
with_checker(build_microvm_with_template, spectre_meltdown_checker),
REMOTE_CHECKER_COMMAND,
comparator=set_did_not_grow_comparator(
@@ -290,7 +287,7 @@ def test_spectre_meltdown_checker_on_guest_with_custom_template(
"""
Test with the spectre / meltdown checker on guest with a custom CPU template.
"""
- git_ab_test_guest_command_if_pr(
+ precompiled_ab_test_guest_command_if_pr(
with_checker(build_microvm_with_custom_template, spectre_meltdown_checker),
REMOTE_CHECKER_COMMAND,
comparator=set_did_not_grow_comparator(
@@ -305,7 +302,7 @@ def test_spectre_meltdown_checker_on_restored_guest_with_template(
"""
Test with the spectre / meltdown checker on a restored guest with a CPU template.
"""
- git_ab_test_guest_command_if_pr(
+ precompiled_ab_test_guest_command_if_pr(
with_checker(
with_restore(build_microvm_with_template, microvm_factory),
spectre_meltdown_checker,
@@ -325,7 +322,7 @@ def test_spectre_meltdown_checker_on_restored_guest_with_custom_template(
"""
Test with the spectre / meltdown checker on a restored guest with a custom CPU template.
"""
- git_ab_test_guest_command_if_pr(
+ precompiled_ab_test_guest_command_if_pr(
with_checker(
with_restore(build_microvm_with_custom_template, microvm_factory),
spectre_meltdown_checker,
@@ -383,17 +380,15 @@ def get_vuln_files_exception_dict(template):
return exception_dict
+# Nothing can be sensibly tested here in a PR context
+@pytest.mark.skipif(
+ is_pr(), reason="Test depends solely on factors external to GitHub repository"
+)
def test_vulnerabilities_on_host():
"""
Test vulnerabilities files on host.
"""
-
- git_ab_test_host_command_if_pr(
- f"! grep -r Vulnerable {VULN_DIR}",
- comparator=set_did_not_grow_comparator(
- lambda output: set(output.stdout.splitlines())
- ),
- )
+ utils.check_output(f"! grep -r Vulnerable {VULN_DIR}")
def check_vulnerabilities_files_on_guest(microvm):
@@ -429,7 +424,7 @@ def check_vulnerabilities_files_ab(builder):
running in a PR pipeline, and otherwise calls `check_vulnerabilities_files_on_guest`
"""
if is_pr():
- git_ab_test_guest_command(
+ precompiled_ab_test_guest_command(
builder,
f"! grep -r Vulnerable {VULN_DIR}",
comparator=set_did_not_grow_comparator(
diff --git a/tools/ab_test.py b/tools/ab_test.py
index fa76f087cf8..2d03d9591a1 100755
--- a/tools/ab_test.py
+++ b/tools/ab_test.py
@@ -32,10 +32,8 @@
sys.path.append(str(Path(__file__).parent.parent / "tests"))
# pylint:disable=wrong-import-position
-from framework import utils
-from framework.ab_test import check_regression, git_ab_test
+from framework.ab_test import binary_ab_test, check_regression
from framework.properties import global_props
-from host_tools.cargo_build import get_binary
from host_tools.metrics import (
emit_raw_emf,
format_with_reduced_unit,
@@ -107,7 +105,7 @@ def find_unit(emf: dict, metric: str):
return metrics.get(metric, "None")
-def load_data_series(report_path: Path, revision: str = None, *, reemit: bool = False):
+def load_data_series(report_path: Path, tag=None, *, reemit: bool = False):
"""Loads the data series relevant for A/B-testing from test_results/test-report.json
into a dictionary mapping each message's cloudwatch dimensions to a dictionary of
its list-valued properties/metrics.
@@ -126,10 +124,9 @@ def load_data_series(report_path: Path, revision: str = None, *, reemit: bool =
emf = json.loads(line)
if reemit:
- assert revision is not None
+ assert tag is not None
- # These will show up in Cloudwatch, so canonicalize to long commit SHAs
- emf["git_commit_id"] = canonicalize_revision(revision)
+ emf["git_commit_id"] = str(tag)
emit_raw_emf(emf)
dimensions, result = process_log_entry(emf)
@@ -158,8 +155,7 @@ def load_data_series(report_path: Path, revision: str = None, *, reemit: bool =
def collect_data(binary_dir: Path, tests: list[str]):
"""Executes the specified test using the provided firecracker binaries"""
- # Example binary_dir: ../build/main/build/cargo_target/x86_64-unknown-linux-musl/release
- revision = binary_dir.parents[3].name
+ binary_dir = binary_dir.resolve()
print(f"Collecting samples with {binary_dir}")
subprocess.run(
@@ -172,7 +168,7 @@ def collect_data(binary_dir: Path, tests: list[str]):
check=True,
)
return load_data_series(
- Path("test_results/test-report.json"), revision, reemit=True
+ Path("test_results/test-report.json"), binary_dir, reemit=True
)
@@ -311,23 +307,17 @@ def analyze_data(
def ab_performance_test(
- a_revision, b_revision, tests, p_thresh, strength_abs_thresh, noise_threshold
+ a_revision: Path,
+ b_revision: Path,
+ tests,
+ p_thresh,
+ strength_abs_thresh,
+ noise_threshold,
):
- """Does an A/B-test of the specified test across the given revisions"""
- _, commit_list, _ = utils.check_output(
- f"git --no-pager log --oneline {a_revision}..{b_revision}"
- )
- print(
- f"Performance A/B-test across {a_revision}..{b_revision}. This includes the following commits:"
- )
- print(commit_list.strip())
+ """Does an A/B-test of the specified test with the given firecracker/jailer binaries"""
- def test_runner(workspace, _is_ab: bool):
- bin_dir = get_binary("firecracker", workspace_dir=workspace).parent
- return collect_data(bin_dir, tests)
-
- return git_ab_test(
- test_runner,
+ return binary_ab_test(
+ lambda bin_dir, _: collect_data(bin_dir, tests),
lambda ah, be: analyze_data(
ah,
be,
@@ -336,16 +326,11 @@ def test_runner(workspace, _is_ab: bool):
noise_threshold,
n_resamples=int(100 / p_thresh),
),
- a_revision=a_revision,
- b_revision=b_revision,
+ a_directory=a_revision,
+ b_directory=b_revision,
)
-def canonicalize_revision(revision):
- """Canonicalizes the given revision to a 40 digit hex SHA"""
- return utils.check_output(f"git rev-parse {revision}").stdout.strip()
-
-
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Executes Firecracker's A/B testsuite across the specified commits"
@@ -357,11 +342,13 @@ def canonicalize_revision(revision):
)
run_parser.add_argument(
"a_revision",
- help="The baseline revision compared to which we want to avoid regressing",
+ help="Directory containing firecracker and jailer binaries to be considered the performance baseline",
+ type=Path,
)
run_parser.add_argument(
"b_revision",
- help="The revision whose performance we want to compare against the results from a_revision",
+ help="Directory containing firecracker and jailer binaries whose performance we want to compare against the results from a_revision",
+ type=Path,
)
run_parser.add_argument("--test", help="The test to run", nargs="+", required=True)
analyze_parser = subparsers.add_parser(
diff --git a/tools/create_snapshot_artifact/main.py b/tools/create_snapshot_artifact/main.py
deleted file mode 100755
index 75d439c1185..00000000000
--- a/tools/create_snapshot_artifact/main.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-"""Script used to generate snapshots of microVMs."""
-
-import json
-import os
-import platform
-import re
-import shutil
-import sys
-from pathlib import Path
-
-# Hack to be able to import testing framework functions.
-sys.path.append(os.path.join(os.getcwd(), "tests")) # noqa: E402
-
-# pylint: disable=wrong-import-position
-from framework.artifacts import disks, kernels
-from framework.microvm import MicroVMFactory
-from framework.utils import (
- configure_mmds,
- generate_mmds_get_request,
- generate_mmds_session_token,
-)
-from framework.utils_cpu_templates import get_supported_cpu_templates
-from host_tools.cargo_build import get_firecracker_binaries
-
-# pylint: enable=wrong-import-position
-
-# Default IPv4 address to route MMDS requests.
-IPV4_ADDRESS = "169.254.169.254"
-NET_IFACE_FOR_MMDS = "eth3"
-# Root directory for the snapshot artifacts.
-SNAPSHOT_ARTIFACTS_ROOT_DIR = "snapshot_artifacts"
-
-
-def populate_mmds(microvm, data_store):
- """Populate MMDS contents with json data provided."""
- # MMDS should be empty.
- response = microvm.api.mmds.get()
- assert response.json() == {}
-
- # Populate MMDS with data.
- microvm.api.mmds.put(**data_store)
-
- # Ensure data is persistent inside the data store.
- response = microvm.api.mmds.get()
- assert response.json() == data_store
-
-
-def validate_mmds(ssh_connection, data_store):
- """Validate that MMDS contents fetched from the guest."""
- # Configure interface to route MMDS requests
- cmd = "ip route add {} dev {}".format(IPV4_ADDRESS, NET_IFACE_FOR_MMDS)
- _, stdout, stderr = ssh_connection.run(cmd)
- assert stdout == stderr == ""
-
- # Fetch metadata to ensure MMDS is accessible.
- token = generate_mmds_session_token(ssh_connection, IPV4_ADDRESS, token_ttl=60)
-
- cmd = generate_mmds_get_request(IPV4_ADDRESS, token=token)
- _, stdout, _ = ssh_connection.run(cmd)
- assert json.loads(stdout) == data_store
-
-
-def main():
- """
- Run the main logic.
-
- Create snapshot artifacts from complex microVMs with all Firecracker's
- functionality enabled. The kernels are parametrized to include all guest
- supported versions.
-
- Artifacts are saved in the following format:
- snapshot_artifacts
- |
- -> __guest_snapshot
- |
- -> vm.mem
- -> vm.vmstate
- -> ubuntu-22.04.id_rsa
- -> ubuntu-22.04.ext4
- -> __guest_snapshot
- |
- ...
- """
- # Create directory dedicated to store snapshot artifacts for
- # each guest kernel version.
- print("Cleanup")
- shutil.rmtree(SNAPSHOT_ARTIFACTS_ROOT_DIR, ignore_errors=True)
- vm_factory = MicroVMFactory(*get_firecracker_binaries())
-
- cpu_templates = []
- if platform.machine() == "x86_64":
- cpu_templates = ["None"]
- cpu_templates += get_supported_cpu_templates()
-
- for cpu_template in cpu_templates:
- for kernel in kernels(glob="vmlinux-*"):
- for rootfs in disks(glob="ubuntu-*.squashfs"):
- print(kernel, rootfs, cpu_template)
- vm = vm_factory.build(kernel, rootfs)
- vm.spawn(log_level="Info")
- vm.basic_config(
- vcpu_count=2,
- mem_size_mib=1024,
- cpu_template=cpu_template,
- track_dirty_pages=True,
- )
- # Add 4 network devices
- for i in range(4):
- vm.add_net_iface()
- # Add a vsock device
- vm.api.vsock.put(vsock_id="vsock0", guest_cid=3, uds_path="/v.sock")
- # Add MMDS
- configure_mmds(vm, ["eth3"], version="V2")
- # Add a memory balloon.
- vm.api.balloon.put(
- amount_mib=0, deflate_on_oom=True, stats_polling_interval_s=1
- )
-
- vm.start()
-
- # Populate MMDS.
- data_store = {
- "latest": {
- "meta-data": {
- "ami-id": "ami-12345678",
- "reservation-id": "r-fea54097",
- "local-hostname": "ip-10-251-50-12.ec2.internal",
- "public-hostname": "ec2-203-0-113-25.compute-1.amazonaws.com",
- }
- }
- }
- populate_mmds(vm, data_store)
-
- # Iterate and validate connectivity on all ifaces after boot.
- for i in range(4):
- exit_code, _, _ = vm.ssh_iface(i).run("sync")
- assert exit_code == 0
-
- # Validate MMDS.
- validate_mmds(vm.ssh, data_store)
-
- # Snapshot the microVM.
- snapshot = vm.snapshot_diff()
-
- # Create snapshot artifacts directory specific for the kernel version used.
- guest_kernel_version = re.search("vmlinux-(.*)", kernel.name)
-
- snapshot_artifacts_dir = (
- Path(SNAPSHOT_ARTIFACTS_ROOT_DIR)
- / f"{guest_kernel_version.group(1)}_{cpu_template}_guest_snapshot"
- )
- snapshot_artifacts_dir.mkdir(parents=True)
- snapshot.save_to(snapshot_artifacts_dir)
- print(f"Copied snapshot to: {snapshot_artifacts_dir}.")
-
- vm.kill()
-
-
-if __name__ == "__main__":
- main()
diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile
index eef52632a6a..f0c7c36f759 100644
--- a/tools/devctr/Dockerfile
+++ b/tools/devctr/Dockerfile
@@ -75,7 +75,7 @@ RUN apt-get update \
screen tmux \
tzdata \
tini \
- squashfs-tools \
+ squashfs-tools zstd \
# for aws-lc-rs
cmake \
# for Qemu vhost-user-blk backend
@@ -83,7 +83,7 @@ RUN apt-get update \
# for crosvm (vhost-user-blk backend)
libcap2 \
# for debugging
- gdb strace \
+ gdb strace trace-cmd \
&& rm -rf /var/lib/apt/lists/* \
&& pip3 install --upgrade poetry
@@ -107,7 +107,7 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-too
&& rustup target add x86_64-unknown-linux-musl \
&& rustup target add aarch64-unknown-linux-musl \
&& rustup component add llvm-tools-preview clippy rustfmt \
- && cargo install --locked cargo-audit cargo-deny grcov cargo-sort cargo-afl \
+ && cargo install --locked cargo-audit cargo-deny@0.16.1 grcov cargo-sort cargo-afl \
&& cargo install --locked kani-verifier && cargo kani setup \
\
&& apt-get update \
diff --git a/tools/devctr/poetry.lock b/tools/devctr/poetry.lock
index fef3e284ade..96f1d0c990a 100644
--- a/tools/devctr/poetry.lock
+++ b/tools/devctr/poetry.lock
@@ -13,112 +13,112 @@ files = [
[[package]]
name = "aiohttp"
-version = "3.10.5"
+version = "3.10.11"
description = "Async http client/server framework (asyncio)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:18a01eba2574fb9edd5f6e5fb25f66e6ce061da5dab5db75e13fe1558142e0a3"},
- {file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:94fac7c6e77ccb1ca91e9eb4cb0ac0270b9fb9b289738654120ba8cebb1189c6"},
- {file = "aiohttp-3.10.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2f1f1c75c395991ce9c94d3e4aa96e5c59c8356a15b1c9231e783865e2772699"},
- {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f7acae3cf1a2a2361ec4c8e787eaaa86a94171d2417aae53c0cca6ca3118ff6"},
- {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:94c4381ffba9cc508b37d2e536b418d5ea9cfdc2848b9a7fea6aebad4ec6aac1"},
- {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c31ad0c0c507894e3eaa843415841995bf8de4d6b2d24c6e33099f4bc9fc0d4f"},
- {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0912b8a8fadeb32ff67a3ed44249448c20148397c1ed905d5dac185b4ca547bb"},
- {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d93400c18596b7dc4794d48a63fb361b01a0d8eb39f28800dc900c8fbdaca91"},
- {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3c5e0d764a5c9aa5a62d99728c56d455310bcc288a79cab10157b3af426f"},
- {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d742c36ed44f2798c8d3f4bc511f479b9ceef2b93f348671184139e7d708042c"},
- {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:814375093edae5f1cb31e3407997cf3eacefb9010f96df10d64829362ae2df69"},
- {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8224f98be68a84b19f48e0bdc14224b5a71339aff3a27df69989fa47d01296f3"},
- {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9a487ef090aea982d748b1b0d74fe7c3950b109df967630a20584f9a99c0683"},
- {file = "aiohttp-3.10.5-cp310-cp310-win32.whl", hash = "sha256:d9ef084e3dc690ad50137cc05831c52b6ca428096e6deb3c43e95827f531d5ef"},
- {file = "aiohttp-3.10.5-cp310-cp310-win_amd64.whl", hash = "sha256:66bf9234e08fe561dccd62083bf67400bdbf1c67ba9efdc3dac03650e97c6088"},
- {file = "aiohttp-3.10.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8c6a4e5e40156d72a40241a25cc226051c0a8d816610097a8e8f517aeacd59a2"},
- {file = "aiohttp-3.10.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c634a3207a5445be65536d38c13791904fda0748b9eabf908d3fe86a52941cf"},
- {file = "aiohttp-3.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4aff049b5e629ef9b3e9e617fa6e2dfeda1bf87e01bcfecaf3949af9e210105e"},
- {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1942244f00baaacaa8155eca94dbd9e8cc7017deb69b75ef67c78e89fdad3c77"},
- {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e04a1f2a65ad2f93aa20f9ff9f1b672bf912413e5547f60749fa2ef8a644e061"},
- {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7f2bfc0032a00405d4af2ba27f3c429e851d04fad1e5ceee4080a1c570476697"},
- {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:424ae21498790e12eb759040bbb504e5e280cab64693d14775c54269fd1d2bb7"},
- {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:975218eee0e6d24eb336d0328c768ebc5d617609affaca5dbbd6dd1984f16ed0"},
- {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4120d7fefa1e2d8fb6f650b11489710091788de554e2b6f8347c7a20ceb003f5"},
- {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b90078989ef3fc45cf9221d3859acd1108af7560c52397ff4ace8ad7052a132e"},
- {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ba5a8b74c2a8af7d862399cdedce1533642fa727def0b8c3e3e02fcb52dca1b1"},
- {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:02594361128f780eecc2a29939d9dfc870e17b45178a867bf61a11b2a4367277"},
- {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8fb4fc029e135859f533025bc82047334e24b0d489e75513144f25408ecaf058"},
- {file = "aiohttp-3.10.5-cp311-cp311-win32.whl", hash = "sha256:e1ca1ef5ba129718a8fc827b0867f6aa4e893c56eb00003b7367f8a733a9b072"},
- {file = "aiohttp-3.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:349ef8a73a7c5665cca65c88ab24abe75447e28aa3bc4c93ea5093474dfdf0ff"},
- {file = "aiohttp-3.10.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:305be5ff2081fa1d283a76113b8df7a14c10d75602a38d9f012935df20731487"},
- {file = "aiohttp-3.10.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3a1c32a19ee6bbde02f1cb189e13a71b321256cc1d431196a9f824050b160d5a"},
- {file = "aiohttp-3.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:61645818edd40cc6f455b851277a21bf420ce347baa0b86eaa41d51ef58ba23d"},
- {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c225286f2b13bab5987425558baa5cbdb2bc925b2998038fa028245ef421e75"},
- {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ba01ebc6175e1e6b7275c907a3a36be48a2d487549b656aa90c8a910d9f3178"},
- {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8eaf44ccbc4e35762683078b72bf293f476561d8b68ec8a64f98cf32811c323e"},
- {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c43eb1ab7cbf411b8e387dc169acb31f0ca0d8c09ba63f9eac67829585b44f"},
- {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de7a5299827253023c55ea549444e058c0eb496931fa05d693b95140a947cb73"},
- {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4790f0e15f00058f7599dab2b206d3049d7ac464dc2e5eae0e93fa18aee9e7bf"},
- {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:44b324a6b8376a23e6ba25d368726ee3bc281e6ab306db80b5819999c737d820"},
- {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0d277cfb304118079e7044aad0b76685d30ecb86f83a0711fc5fb257ffe832ca"},
- {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:54d9ddea424cd19d3ff6128601a4a4d23d54a421f9b4c0fff740505813739a91"},
- {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4f1c9866ccf48a6df2b06823e6ae80573529f2af3a0992ec4fe75b1a510df8a6"},
- {file = "aiohttp-3.10.5-cp312-cp312-win32.whl", hash = "sha256:dc4826823121783dccc0871e3f405417ac116055bf184ac04c36f98b75aacd12"},
- {file = "aiohttp-3.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:22c0a23a3b3138a6bf76fc553789cb1a703836da86b0f306b6f0dc1617398abc"},
- {file = "aiohttp-3.10.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7f6b639c36734eaa80a6c152a238242bedcee9b953f23bb887e9102976343092"},
- {file = "aiohttp-3.10.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f29930bc2921cef955ba39a3ff87d2c4398a0394ae217f41cb02d5c26c8b1b77"},
- {file = "aiohttp-3.10.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f489a2c9e6455d87eabf907ac0b7d230a9786be43fbe884ad184ddf9e9c1e385"},
- {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:123dd5b16b75b2962d0fff566effb7a065e33cd4538c1692fb31c3bda2bfb972"},
- {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b98e698dc34966e5976e10bbca6d26d6724e6bdea853c7c10162a3235aba6e16"},
- {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3b9162bab7e42f21243effc822652dc5bb5e8ff42a4eb62fe7782bcbcdfacf6"},
- {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1923a5c44061bffd5eebeef58cecf68096e35003907d8201a4d0d6f6e387ccaa"},
- {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d55f011da0a843c3d3df2c2cf4e537b8070a419f891c930245f05d329c4b0689"},
- {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:afe16a84498441d05e9189a15900640a2d2b5e76cf4efe8cbb088ab4f112ee57"},
- {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8112fb501b1e0567a1251a2fd0747baae60a4ab325a871e975b7bb67e59221f"},
- {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1e72589da4c90337837fdfe2026ae1952c0f4a6e793adbbfbdd40efed7c63599"},
- {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4d46c7b4173415d8e583045fbc4daa48b40e31b19ce595b8d92cf639396c15d5"},
- {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:33e6bc4bab477c772a541f76cd91e11ccb6d2efa2b8d7d7883591dfb523e5987"},
- {file = "aiohttp-3.10.5-cp313-cp313-win32.whl", hash = "sha256:c58c6837a2c2a7cf3133983e64173aec11f9c2cd8e87ec2fdc16ce727bcf1a04"},
- {file = "aiohttp-3.10.5-cp313-cp313-win_amd64.whl", hash = "sha256:38172a70005252b6893088c0f5e8a47d173df7cc2b2bd88650957eb84fcf5022"},
- {file = "aiohttp-3.10.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f6f18898ace4bcd2d41a122916475344a87f1dfdec626ecde9ee802a711bc569"},
- {file = "aiohttp-3.10.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5ede29d91a40ba22ac1b922ef510aab871652f6c88ef60b9dcdf773c6d32ad7a"},
- {file = "aiohttp-3.10.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:673f988370f5954df96cc31fd99c7312a3af0a97f09e407399f61583f30da9bc"},
- {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58718e181c56a3c02d25b09d4115eb02aafe1a732ce5714ab70326d9776457c3"},
- {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b38b1570242fbab8d86a84128fb5b5234a2f70c2e32f3070143a6d94bc854cf"},
- {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:074d1bff0163e107e97bd48cad9f928fa5a3eb4b9d33366137ffce08a63e37fe"},
- {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd31f176429cecbc1ba499d4aba31aaccfea488f418d60376b911269d3b883c5"},
- {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7384d0b87d4635ec38db9263e6a3f1eb609e2e06087f0aa7f63b76833737b471"},
- {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8989f46f3d7ef79585e98fa991e6ded55d2f48ae56d2c9fa5e491a6e4effb589"},
- {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:c83f7a107abb89a227d6c454c613e7606c12a42b9a4ca9c5d7dad25d47c776ae"},
- {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cde98f323d6bf161041e7627a5fd763f9fd829bcfcd089804a5fdce7bb6e1b7d"},
- {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:676f94c5480d8eefd97c0c7e3953315e4d8c2b71f3b49539beb2aa676c58272f"},
- {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2d21ac12dc943c68135ff858c3a989f2194a709e6e10b4c8977d7fcd67dfd511"},
- {file = "aiohttp-3.10.5-cp38-cp38-win32.whl", hash = "sha256:17e997105bd1a260850272bfb50e2a328e029c941c2708170d9d978d5a30ad9a"},
- {file = "aiohttp-3.10.5-cp38-cp38-win_amd64.whl", hash = "sha256:1c19de68896747a2aa6257ae4cf6ef59d73917a36a35ee9d0a6f48cff0f94db8"},
- {file = "aiohttp-3.10.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7e2fe37ac654032db1f3499fe56e77190282534810e2a8e833141a021faaab0e"},
- {file = "aiohttp-3.10.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5bf3ead3cb66ab990ee2561373b009db5bc0e857549b6c9ba84b20bc462e172"},
- {file = "aiohttp-3.10.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b2c16a919d936ca87a3c5f0e43af12a89a3ce7ccbce59a2d6784caba945b68b"},
- {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad146dae5977c4dd435eb31373b3fe9b0b1bf26858c6fc452bf6af394067e10b"},
- {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c5c6fa16412b35999320f5c9690c0f554392dc222c04e559217e0f9ae244b92"},
- {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:95c4dc6f61d610bc0ee1edc6f29d993f10febfe5b76bb470b486d90bbece6b22"},
- {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da452c2c322e9ce0cfef392e469a26d63d42860f829026a63374fde6b5c5876f"},
- {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:898715cf566ec2869d5cb4d5fb4be408964704c46c96b4be267442d265390f32"},
- {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:391cc3a9c1527e424c6865e087897e766a917f15dddb360174a70467572ac6ce"},
- {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:380f926b51b92d02a34119d072f178d80bbda334d1a7e10fa22d467a66e494db"},
- {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce91db90dbf37bb6fa0997f26574107e1b9d5ff939315247b7e615baa8ec313b"},
- {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9093a81e18c45227eebe4c16124ebf3e0d893830c6aca7cc310bfca8fe59d857"},
- {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ee40b40aa753d844162dcc80d0fe256b87cba48ca0054f64e68000453caead11"},
- {file = "aiohttp-3.10.5-cp39-cp39-win32.whl", hash = "sha256:03f2645adbe17f274444953bdea69f8327e9d278d961d85657cb0d06864814c1"},
- {file = "aiohttp-3.10.5-cp39-cp39-win_amd64.whl", hash = "sha256:d17920f18e6ee090bdd3d0bfffd769d9f2cb4c8ffde3eb203777a3895c128862"},
- {file = "aiohttp-3.10.5.tar.gz", hash = "sha256:f071854b47d39591ce9a17981c46790acb30518e2f83dfca8db2dfa091178691"},
+ {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"},
+ {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"},
+ {file = "aiohttp-3.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffbfde2443696345e23a3c597049b1dd43049bb65337837574205e7368472177"},
+ {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b3d9e416774d41813bc02fdc0663379c01817b0874b932b81c7f777f67b217"},
+ {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b943011b45ee6bf74b22245c6faab736363678e910504dd7531a58c76c9015a"},
+ {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48bc1d924490f0d0b3658fe5c4b081a4d56ebb58af80a6729d4bd13ea569797a"},
+ {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e12eb3f4b1f72aaaf6acd27d045753b18101524f72ae071ae1c91c1cd44ef115"},
+ {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f14ebc419a568c2eff3c1ed35f634435c24ead2fe19c07426af41e7adb68713a"},
+ {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:72b191cdf35a518bfc7ca87d770d30941decc5aaf897ec8b484eb5cc8c7706f3"},
+ {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ab2328a61fdc86424ee540d0aeb8b73bbcad7351fb7cf7a6546fc0bcffa0038"},
+ {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aa93063d4af05c49276cf14e419550a3f45258b6b9d1f16403e777f1addf4519"},
+ {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:30283f9d0ce420363c24c5c2421e71a738a2155f10adbb1a11a4d4d6d2715cfc"},
+ {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e5358addc8044ee49143c546d2182c15b4ac3a60be01c3209374ace05af5733d"},
+ {file = "aiohttp-3.10.11-cp310-cp310-win32.whl", hash = "sha256:e1ffa713d3ea7cdcd4aea9cddccab41edf6882fa9552940344c44e59652e1120"},
+ {file = "aiohttp-3.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:778cbd01f18ff78b5dd23c77eb82987ee4ba23408cbed233009fd570dda7e674"},
+ {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:80ff08556c7f59a7972b1e8919f62e9c069c33566a6d28586771711e0eea4f07"},
+ {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c8f96e9ee19f04c4914e4e7a42a60861066d3e1abf05c726f38d9d0a466e695"},
+ {file = "aiohttp-3.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fb8601394d537da9221947b5d6e62b064c9a43e88a1ecd7414d21a1a6fba9c24"},
+ {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea224cf7bc2d8856d6971cea73b1d50c9c51d36971faf1abc169a0d5f85a382"},
+ {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db9503f79e12d5d80b3efd4d01312853565c05367493379df76d2674af881caa"},
+ {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f449a50cc33f0384f633894d8d3cd020e3ccef81879c6e6245c3c375c448625"},
+ {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82052be3e6d9e0c123499127782a01a2b224b8af8c62ab46b3f6197035ad94e9"},
+ {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20063c7acf1eec550c8eb098deb5ed9e1bb0521613b03bb93644b810986027ac"},
+ {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:489cced07a4c11488f47aab1f00d0c572506883f877af100a38f1fedaa884c3a"},
+ {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea9b3bab329aeaa603ed3bf605f1e2a6f36496ad7e0e1aa42025f368ee2dc07b"},
+ {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ca117819d8ad113413016cb29774b3f6d99ad23c220069789fc050267b786c16"},
+ {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2dfb612dcbe70fb7cdcf3499e8d483079b89749c857a8f6e80263b021745c730"},
+ {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9b615d3da0d60e7d53c62e22b4fd1c70f4ae5993a44687b011ea3a2e49051b8"},
+ {file = "aiohttp-3.10.11-cp311-cp311-win32.whl", hash = "sha256:29103f9099b6068bbdf44d6a3d090e0a0b2be6d3c9f16a070dd9d0d910ec08f9"},
+ {file = "aiohttp-3.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:236b28ceb79532da85d59aa9b9bf873b364e27a0acb2ceaba475dc61cffb6f3f"},
+ {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7480519f70e32bfb101d71fb9a1f330fbd291655a4c1c922232a48c458c52710"},
+ {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f65267266c9aeb2287a6622ee2bb39490292552f9fbf851baabc04c9f84e048d"},
+ {file = "aiohttp-3.10.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7400a93d629a0608dc1d6c55f1e3d6e07f7375745aaa8bd7f085571e4d1cee97"},
+ {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f34b97e4b11b8d4eb2c3a4f975be626cc8af99ff479da7de49ac2c6d02d35725"},
+ {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e7b825da878464a252ccff2958838f9caa82f32a8dbc334eb9b34a026e2c636"},
+ {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9f92a344c50b9667827da308473005f34767b6a2a60d9acff56ae94f895f385"},
+ {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f1ab987a27b83c5268a17218463c2ec08dbb754195113867a27b166cd6087"},
+ {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1dc0f4ca54842173d03322793ebcf2c8cc2d34ae91cc762478e295d8e361e03f"},
+ {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7ce6a51469bfaacff146e59e7fb61c9c23006495d11cc24c514a455032bcfa03"},
+ {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aad3cd91d484d065ede16f3cf15408254e2469e3f613b241a1db552c5eb7ab7d"},
+ {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f4df4b8ca97f658c880fb4b90b1d1ec528315d4030af1ec763247ebfd33d8b9a"},
+ {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e4e18a0a2d03531edbc06c366954e40a3f8d2a88d2b936bbe78a0c75a3aab3e"},
+ {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ce66780fa1a20e45bc753cda2a149daa6dbf1561fc1289fa0c308391c7bc0a4"},
+ {file = "aiohttp-3.10.11-cp312-cp312-win32.whl", hash = "sha256:a919c8957695ea4c0e7a3e8d16494e3477b86f33067478f43106921c2fef15bb"},
+ {file = "aiohttp-3.10.11-cp312-cp312-win_amd64.whl", hash = "sha256:b5e29706e6389a2283a91611c91bf24f218962717c8f3b4e528ef529d112ee27"},
+ {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:703938e22434d7d14ec22f9f310559331f455018389222eed132808cd8f44127"},
+ {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9bc50b63648840854e00084c2b43035a62e033cb9b06d8c22b409d56eb098413"},
+ {file = "aiohttp-3.10.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f0463bf8b0754bc744e1feb61590706823795041e63edf30118a6f0bf577461"},
+ {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6c6dec398ac5a87cb3a407b068e1106b20ef001c344e34154616183fe684288"},
+ {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcaf2d79104d53d4dcf934f7ce76d3d155302d07dae24dff6c9fffd217568067"},
+ {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25fd5470922091b5a9aeeb7e75be609e16b4fba81cdeaf12981393fb240dd10e"},
+ {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbde2ca67230923a42161b1f408c3992ae6e0be782dca0c44cb3206bf330dee1"},
+ {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:249c8ff8d26a8b41a0f12f9df804e7c685ca35a207e2410adbd3e924217b9006"},
+ {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:878ca6a931ee8c486a8f7b432b65431d095c522cbeb34892bee5be97b3481d0f"},
+ {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8663f7777ce775f0413324be0d96d9730959b2ca73d9b7e2c2c90539139cbdd6"},
+ {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6cd3f10b01f0c31481fba8d302b61603a2acb37b9d30e1d14e0f5a58b7b18a31"},
+ {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e8d8aad9402d3aa02fdc5ca2fe68bcb9fdfe1f77b40b10410a94c7f408b664d"},
+ {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:38e3c4f80196b4f6c3a85d134a534a56f52da9cb8d8e7af1b79a32eefee73a00"},
+ {file = "aiohttp-3.10.11-cp313-cp313-win32.whl", hash = "sha256:fc31820cfc3b2863c6e95e14fcf815dc7afe52480b4dc03393c4873bb5599f71"},
+ {file = "aiohttp-3.10.11-cp313-cp313-win_amd64.whl", hash = "sha256:4996ff1345704ffdd6d75fb06ed175938c133425af616142e7187f28dc75f14e"},
+ {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:74baf1a7d948b3d640badeac333af581a367ab916b37e44cf90a0334157cdfd2"},
+ {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:473aebc3b871646e1940c05268d451f2543a1d209f47035b594b9d4e91ce8339"},
+ {file = "aiohttp-3.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c2f746a6968c54ab2186574e15c3f14f3e7f67aef12b761e043b33b89c5b5f95"},
+ {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d110cabad8360ffa0dec8f6ec60e43286e9d251e77db4763a87dcfe55b4adb92"},
+ {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0099c7d5d7afff4202a0c670e5b723f7718810000b4abcbc96b064129e64bc7"},
+ {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0316e624b754dbbf8c872b62fe6dcb395ef20c70e59890dfa0de9eafccd2849d"},
+ {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a5f7ab8baf13314e6b2485965cbacb94afff1e93466ac4d06a47a81c50f9cca"},
+ {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c891011e76041e6508cbfc469dd1a8ea09bc24e87e4c204e05f150c4c455a5fa"},
+ {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9208299251370ee815473270c52cd3f7069ee9ed348d941d574d1457d2c73e8b"},
+ {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:459f0f32c8356e8125f45eeff0ecf2b1cb6db1551304972702f34cd9e6c44658"},
+ {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:14cdc8c1810bbd4b4b9f142eeee23cda528ae4e57ea0923551a9af4820980e39"},
+ {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:971aa438a29701d4b34e4943e91b5e984c3ae6ccbf80dd9efaffb01bd0b243a9"},
+ {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9a309c5de392dfe0f32ee57fa43ed8fc6ddf9985425e84bd51ed66bb16bce3a7"},
+ {file = "aiohttp-3.10.11-cp38-cp38-win32.whl", hash = "sha256:9ec1628180241d906a0840b38f162a3215114b14541f1a8711c368a8739a9be4"},
+ {file = "aiohttp-3.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:9c6e0ffd52c929f985c7258f83185d17c76d4275ad22e90aa29f38e211aacbec"},
+ {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cdc493a2e5d8dc79b2df5bec9558425bcd39aff59fc949810cbd0832e294b106"},
+ {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3e70f24e7d0405be2348da9d5a7836936bf3a9b4fd210f8c37e8d48bc32eca6"},
+ {file = "aiohttp-3.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968b8fb2a5eee2770eda9c7b5581587ef9b96fbdf8dcabc6b446d35ccc69df01"},
+ {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deef4362af9493d1382ef86732ee2e4cbc0d7c005947bd54ad1a9a16dd59298e"},
+ {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:686b03196976e327412a1b094f4120778c7c4b9cff9bce8d2fdfeca386b89829"},
+ {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bf6d027d9d1d34e1c2e1645f18a6498c98d634f8e373395221121f1c258ace8"},
+ {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:099fd126bf960f96d34a760e747a629c27fb3634da5d05c7ef4d35ef4ea519fc"},
+ {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c73c4d3dae0b4644bc21e3de546530531d6cdc88659cdeb6579cd627d3c206aa"},
+ {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0c5580f3c51eea91559db3facd45d72e7ec970b04528b4709b1f9c2555bd6d0b"},
+ {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fdf6429f0caabfd8a30c4e2eaecb547b3c340e4730ebfe25139779b9815ba138"},
+ {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d97187de3c276263db3564bb9d9fad9e15b51ea10a371ffa5947a5ba93ad6777"},
+ {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0acafb350cfb2eba70eb5d271f55e08bd4502ec35e964e18ad3e7d34d71f7261"},
+ {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c13ed0c779911c7998a58e7848954bd4d63df3e3575f591e321b19a2aec8df9f"},
+ {file = "aiohttp-3.10.11-cp39-cp39-win32.whl", hash = "sha256:22b7c540c55909140f63ab4f54ec2c20d2635c0289cdd8006da46f3327f971b9"},
+ {file = "aiohttp-3.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:7b26b1551e481012575dab8e3727b16fe7dd27eb2711d2e63ced7368756268fb"},
+ {file = "aiohttp-3.10.11.tar.gz", hash = "sha256:9dc2b8f3dcab2e39e0fa309c8da50c3b55e6f34ab25f1a71d3288f24924d33a7"},
]
[package.dependencies]
aiohappyeyeballs = ">=2.3.0"
aiosignal = ">=1.1.2"
-async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""}
+async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""}
attrs = ">=17.3.0"
frozenlist = ">=1.1.1"
multidict = ">=4.5,<7.0"
-yarl = ">=1.0,<2.0"
+yarl = ">=1.12.0,<2.0"
[package.extras]
speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"]
@@ -1317,6 +1317,113 @@ files = [
[package.dependencies]
wcwidth = "*"
+[[package]]
+name = "propcache"
+version = "0.2.0"
+description = "Accelerated property cache"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"},
+ {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"},
+ {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"},
+ {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"},
+ {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"},
+ {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"},
+ {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"},
+ {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"},
+ {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"},
+ {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"},
+ {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"},
+ {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"},
+ {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"},
+ {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"},
+ {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"},
+ {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"},
+ {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"},
+ {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"},
+ {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"},
+ {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"},
+ {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"},
+ {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"},
+ {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"},
+ {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"},
+ {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"},
+ {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"},
+ {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"},
+ {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"},
+ {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"},
+ {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"},
+ {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"},
+ {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"},
+]
+
[[package]]
name = "psutil"
version = "6.0.0"
@@ -2155,108 +2262,99 @@ files = [
[[package]]
name = "yarl"
-version = "1.11.1"
+version = "1.17.2"
description = "Yet another URL library"
optional = false
-python-versions = ">=3.8"
-files = [
- {file = "yarl-1.11.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:400cd42185f92de559d29eeb529e71d80dfbd2f45c36844914a4a34297ca6f00"},
- {file = "yarl-1.11.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8258c86f47e080a258993eed877d579c71da7bda26af86ce6c2d2d072c11320d"},
- {file = "yarl-1.11.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2164cd9725092761fed26f299e3f276bb4b537ca58e6ff6b252eae9631b5c96e"},
- {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08ea567c16f140af8ddc7cb58e27e9138a1386e3e6e53982abaa6f2377b38cc"},
- {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:768ecc550096b028754ea28bf90fde071c379c62c43afa574edc6f33ee5daaec"},
- {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2909fa3a7d249ef64eeb2faa04b7957e34fefb6ec9966506312349ed8a7e77bf"},
- {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01a8697ec24f17c349c4f655763c4db70eebc56a5f82995e5e26e837c6eb0e49"},
- {file = "yarl-1.11.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e286580b6511aac7c3268a78cdb861ec739d3e5a2a53b4809faef6b49778eaff"},
- {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4179522dc0305c3fc9782549175c8e8849252fefeb077c92a73889ccbcd508ad"},
- {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:27fcb271a41b746bd0e2a92182df507e1c204759f460ff784ca614e12dd85145"},
- {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f61db3b7e870914dbd9434b560075e0366771eecbe6d2b5561f5bc7485f39efd"},
- {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:c92261eb2ad367629dc437536463dc934030c9e7caca861cc51990fe6c565f26"},
- {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d95b52fbef190ca87d8c42f49e314eace4fc52070f3dfa5f87a6594b0c1c6e46"},
- {file = "yarl-1.11.1-cp310-cp310-win32.whl", hash = "sha256:489fa8bde4f1244ad6c5f6d11bb33e09cf0d1d0367edb197619c3e3fc06f3d91"},
- {file = "yarl-1.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:476e20c433b356e16e9a141449f25161e6b69984fb4cdbd7cd4bd54c17844998"},
- {file = "yarl-1.11.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:946eedc12895873891aaceb39bceb484b4977f70373e0122da483f6c38faaa68"},
- {file = "yarl-1.11.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:21a7c12321436b066c11ec19c7e3cb9aec18884fe0d5b25d03d756a9e654edfe"},
- {file = "yarl-1.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c35f493b867912f6fda721a59cc7c4766d382040bdf1ddaeeaa7fa4d072f4675"},
- {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25861303e0be76b60fddc1250ec5986c42f0a5c0c50ff57cc30b1be199c00e63"},
- {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4b53f73077e839b3f89c992223f15b1d2ab314bdbdf502afdc7bb18e95eae27"},
- {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:327c724b01b8641a1bf1ab3b232fb638706e50f76c0b5bf16051ab65c868fac5"},
- {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4307d9a3417eea87715c9736d050c83e8c1904e9b7aada6ce61b46361b733d92"},
- {file = "yarl-1.11.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a28bed68ab8fb7e380775f0029a079f08a17799cb3387a65d14ace16c12e2b"},
- {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:067b961853c8e62725ff2893226fef3d0da060656a9827f3f520fb1d19b2b68a"},
- {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8215f6f21394d1f46e222abeb06316e77ef328d628f593502d8fc2a9117bde83"},
- {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:498442e3af2a860a663baa14fbf23fb04b0dd758039c0e7c8f91cb9279799bff"},
- {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:69721b8effdb588cb055cc22f7c5105ca6fdaa5aeb3ea09021d517882c4a904c"},
- {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e969fa4c1e0b1a391f3fcbcb9ec31e84440253325b534519be0d28f4b6b533e"},
- {file = "yarl-1.11.1-cp311-cp311-win32.whl", hash = "sha256:7d51324a04fc4b0e097ff8a153e9276c2593106a811704025bbc1d6916f45ca6"},
- {file = "yarl-1.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:15061ce6584ece023457fb8b7a7a69ec40bf7114d781a8c4f5dcd68e28b5c53b"},
- {file = "yarl-1.11.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a4264515f9117be204935cd230fb2a052dd3792789cc94c101c535d349b3dab0"},
- {file = "yarl-1.11.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f41fa79114a1d2eddb5eea7b912d6160508f57440bd302ce96eaa384914cd265"},
- {file = "yarl-1.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:02da8759b47d964f9173c8675710720b468aa1c1693be0c9c64abb9d8d9a4867"},
- {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9361628f28f48dcf8b2f528420d4d68102f593f9c2e592bfc842f5fb337e44fd"},
- {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b91044952da03b6f95fdba398d7993dd983b64d3c31c358a4c89e3c19b6f7aef"},
- {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:74db2ef03b442276d25951749a803ddb6e270d02dda1d1c556f6ae595a0d76a8"},
- {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e975a2211952a8a083d1b9d9ba26472981ae338e720b419eb50535de3c02870"},
- {file = "yarl-1.11.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aef97ba1dd2138112890ef848e17d8526fe80b21f743b4ee65947ea184f07a2"},
- {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a7915ea49b0c113641dc4d9338efa9bd66b6a9a485ffe75b9907e8573ca94b84"},
- {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:504cf0d4c5e4579a51261d6091267f9fd997ef58558c4ffa7a3e1460bd2336fa"},
- {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3de5292f9f0ee285e6bd168b2a77b2a00d74cbcfa420ed078456d3023d2f6dff"},
- {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a34e1e30f1774fa35d37202bbeae62423e9a79d78d0874e5556a593479fdf239"},
- {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:66b63c504d2ca43bf7221a1f72fbe981ff56ecb39004c70a94485d13e37ebf45"},
- {file = "yarl-1.11.1-cp312-cp312-win32.whl", hash = "sha256:a28b70c9e2213de425d9cba5ab2e7f7a1c8ca23a99c4b5159bf77b9c31251447"},
- {file = "yarl-1.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:17b5a386d0d36fb828e2fb3ef08c8829c1ebf977eef88e5367d1c8c94b454639"},
- {file = "yarl-1.11.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1fa2e7a406fbd45b61b4433e3aa254a2c3e14c4b3186f6e952d08a730807fa0c"},
- {file = "yarl-1.11.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:750f656832d7d3cb0c76be137ee79405cc17e792f31e0a01eee390e383b2936e"},
- {file = "yarl-1.11.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b8486f322d8f6a38539136a22c55f94d269addb24db5cb6f61adc61eabc9d93"},
- {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fce4da3703ee6048ad4138fe74619c50874afe98b1ad87b2698ef95bf92c96d"},
- {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ed653638ef669e0efc6fe2acb792275cb419bf9cb5c5049399f3556995f23c7"},
- {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18ac56c9dd70941ecad42b5a906820824ca72ff84ad6fa18db33c2537ae2e089"},
- {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:688654f8507464745ab563b041d1fb7dab5d9912ca6b06e61d1c4708366832f5"},
- {file = "yarl-1.11.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4973eac1e2ff63cf187073cd4e1f1148dcd119314ab79b88e1b3fad74a18c9d5"},
- {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:964a428132227edff96d6f3cf261573cb0f1a60c9a764ce28cda9525f18f7786"},
- {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6d23754b9939cbab02c63434776df1170e43b09c6a517585c7ce2b3d449b7318"},
- {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c2dc4250fe94d8cd864d66018f8344d4af50e3758e9d725e94fecfa27588ff82"},
- {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09696438cb43ea6f9492ef237761b043f9179f455f405279e609f2bc9100212a"},
- {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:999bfee0a5b7385a0af5ffb606393509cfde70ecca4f01c36985be6d33e336da"},
- {file = "yarl-1.11.1-cp313-cp313-win32.whl", hash = "sha256:ce928c9c6409c79e10f39604a7e214b3cb69552952fbda8d836c052832e6a979"},
- {file = "yarl-1.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:501c503eed2bb306638ccb60c174f856cc3246c861829ff40eaa80e2f0330367"},
- {file = "yarl-1.11.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dae7bd0daeb33aa3e79e72877d3d51052e8b19c9025ecf0374f542ea8ec120e4"},
- {file = "yarl-1.11.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3ff6b1617aa39279fe18a76c8d165469c48b159931d9b48239065767ee455b2b"},
- {file = "yarl-1.11.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3257978c870728a52dcce8c2902bf01f6c53b65094b457bf87b2644ee6238ddc"},
- {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f351fa31234699d6084ff98283cb1e852270fe9e250a3b3bf7804eb493bd937"},
- {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8aef1b64da41d18026632d99a06b3fefe1d08e85dd81d849fa7c96301ed22f1b"},
- {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7175a87ab8f7fbde37160a15e58e138ba3b2b0e05492d7351314a250d61b1591"},
- {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba444bdd4caa2a94456ef67a2f383710928820dd0117aae6650a4d17029fa25e"},
- {file = "yarl-1.11.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ea9682124fc062e3d931c6911934a678cb28453f957ddccf51f568c2f2b5e05"},
- {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8418c053aeb236b20b0ab8fa6bacfc2feaaf7d4683dd96528610989c99723d5f"},
- {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:61a5f2c14d0a1adfdd82258f756b23a550c13ba4c86c84106be4c111a3a4e413"},
- {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f3a6d90cab0bdf07df8f176eae3a07127daafcf7457b997b2bf46776da2c7eb7"},
- {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:077da604852be488c9a05a524068cdae1e972b7dc02438161c32420fb4ec5e14"},
- {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:15439f3c5c72686b6c3ff235279630d08936ace67d0fe5c8d5bbc3ef06f5a420"},
- {file = "yarl-1.11.1-cp38-cp38-win32.whl", hash = "sha256:238a21849dd7554cb4d25a14ffbfa0ef380bb7ba201f45b144a14454a72ffa5a"},
- {file = "yarl-1.11.1-cp38-cp38-win_amd64.whl", hash = "sha256:67459cf8cf31da0e2cbdb4b040507e535d25cfbb1604ca76396a3a66b8ba37a6"},
- {file = "yarl-1.11.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:884eab2ce97cbaf89f264372eae58388862c33c4f551c15680dd80f53c89a269"},
- {file = "yarl-1.11.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a336eaa7ee7e87cdece3cedb395c9657d227bfceb6781295cf56abcd3386a26"},
- {file = "yarl-1.11.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87f020d010ba80a247c4abc335fc13421037800ca20b42af5ae40e5fd75e7909"},
- {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:637c7ddb585a62d4469f843dac221f23eec3cbad31693b23abbc2c366ad41ff4"},
- {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:48dfd117ab93f0129084577a07287376cc69c08138694396f305636e229caa1a"},
- {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e0ae31fb5ccab6eda09ba1494e87eb226dcbd2372dae96b87800e1dcc98804"},
- {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f46f81501160c28d0c0b7333b4f7be8983dbbc161983b6fb814024d1b4952f79"},
- {file = "yarl-1.11.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04293941646647b3bfb1719d1d11ff1028e9c30199509a844da3c0f5919dc520"},
- {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:250e888fa62d73e721f3041e3a9abf427788a1934b426b45e1b92f62c1f68366"},
- {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e8f63904df26d1a66aabc141bfd258bf738b9bc7bc6bdef22713b4f5ef789a4c"},
- {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:aac44097d838dda26526cffb63bdd8737a2dbdf5f2c68efb72ad83aec6673c7e"},
- {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:267b24f891e74eccbdff42241c5fb4f974de2d6271dcc7d7e0c9ae1079a560d9"},
- {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6907daa4b9d7a688063ed098c472f96e8181733c525e03e866fb5db480a424df"},
- {file = "yarl-1.11.1-cp39-cp39-win32.whl", hash = "sha256:14438dfc5015661f75f85bc5adad0743678eefee266ff0c9a8e32969d5d69f74"},
- {file = "yarl-1.11.1-cp39-cp39-win_amd64.whl", hash = "sha256:94d0caaa912bfcdc702a4204cd5e2bb01eb917fc4f5ea2315aa23962549561b0"},
- {file = "yarl-1.11.1-py3-none-any.whl", hash = "sha256:72bf26f66456baa0584eff63e44545c9f0eaed9b73cb6601b647c91f14c11f38"},
- {file = "yarl-1.11.1.tar.gz", hash = "sha256:1bb2d9e212fb7449b8fb73bc461b51eaa17cc8430b4a87d87be7b25052d92f53"},
+python-versions = ">=3.9"
+files = [
+ {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff"},
+ {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151"},
+ {file = "yarl-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:170ed4971bf9058582b01a8338605f4d8c849bd88834061e60e83b52d0c76870"},
+ {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc61b005f6521fcc00ca0d1243559a5850b9dd1e1fe07b891410ee8fe192d0c0"},
+ {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:871e1b47eec7b6df76b23c642a81db5dd6536cbef26b7e80e7c56c2fd371382e"},
+ {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a58a2f2ca7aaf22b265388d40232f453f67a6def7355a840b98c2d547bd037f"},
+ {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:736bb076f7299c5c55dfef3eb9e96071a795cb08052822c2bb349b06f4cb2e0a"},
+ {file = "yarl-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fd51299e21da709eabcd5b2dd60e39090804431292daacbee8d3dabe39a6bc0"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:358dc7ddf25e79e1cc8ee16d970c23faee84d532b873519c5036dbb858965795"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:50d866f7b1a3f16f98603e095f24c0eeba25eb508c85a2c5939c8b3870ba2df8"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8b9c4643e7d843a0dca9cd9d610a0876e90a1b2cbc4c5ba7930a0d90baf6903f"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d63123bfd0dce5f91101e77c8a5427c3872501acece8c90df457b486bc1acd47"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4e76381be3d8ff96a4e6c77815653063e87555981329cf8f85e5be5abf449021"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:734144cd2bd633a1516948e477ff6c835041c0536cef1d5b9a823ae29899665b"},
+ {file = "yarl-1.17.2-cp310-cp310-win32.whl", hash = "sha256:26bfb6226e0c157af5da16d2d62258f1ac578d2899130a50433ffee4a5dfa673"},
+ {file = "yarl-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:76499469dcc24759399accd85ec27f237d52dec300daaca46a5352fcbebb1071"},
+ {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:792155279dc093839e43f85ff7b9b6493a8eaa0af1f94f1f9c6e8f4de8c63500"},
+ {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38bc4ed5cae853409cb193c87c86cd0bc8d3a70fd2268a9807217b9176093ac6"},
+ {file = "yarl-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4a8c83f6fcdc327783bdc737e8e45b2e909b7bd108c4da1892d3bc59c04a6d84"},
+ {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6d5fed96f0646bfdf698b0a1cebf32b8aae6892d1bec0c5d2d6e2df44e1e2d"},
+ {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:782ca9c58f5c491c7afa55518542b2b005caedaf4685ec814fadfcee51f02493"},
+ {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff6af03cac0d1a4c3c19e5dcc4c05252411bf44ccaa2485e20d0a7c77892ab6e"},
+ {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a3f47930fbbed0f6377639503848134c4aa25426b08778d641491131351c2c8"},
+ {file = "yarl-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1fa68a3c921365c5745b4bd3af6221ae1f0ea1bf04b69e94eda60e57958907f"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:187df91395c11e9f9dc69b38d12406df85aa5865f1766a47907b1cc9855b6303"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:93d1c8cc5bf5df401015c5e2a3ce75a5254a9839e5039c881365d2a9dcfc6dc2"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:11d86c6145ac5c706c53d484784cf504d7d10fa407cb73b9d20f09ff986059ef"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c42774d1d1508ec48c3ed29e7b110e33f5e74a20957ea16197dbcce8be6b52ba"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8e589379ef0407b10bed16cc26e7392ef8f86961a706ade0a22309a45414d7"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1056cadd5e850a1c026f28e0704ab0a94daaa8f887ece8dfed30f88befb87bb0"},
+ {file = "yarl-1.17.2-cp311-cp311-win32.whl", hash = "sha256:be4c7b1c49d9917c6e95258d3d07f43cfba2c69a6929816e77daf322aaba6628"},
+ {file = "yarl-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:ac8eda86cc75859093e9ce390d423aba968f50cf0e481e6c7d7d63f90bae5c9c"},
+ {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dd90238d3a77a0e07d4d6ffdebc0c21a9787c5953a508a2231b5f191455f31e9"},
+ {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c74f0b0472ac40b04e6d28532f55cac8090e34c3e81f118d12843e6df14d0909"},
+ {file = "yarl-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d486ddcaca8c68455aa01cf53d28d413fb41a35afc9f6594a730c9779545876"},
+ {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25b7e93f5414b9a983e1a6c1820142c13e1782cc9ed354c25e933aebe97fcf2"},
+ {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a0baff7827a632204060f48dca9e63fbd6a5a0b8790c1a2adfb25dc2c9c0d50"},
+ {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:460024cacfc3246cc4d9f47a7fc860e4fcea7d1dc651e1256510d8c3c9c7cde0"},
+ {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5870d620b23b956f72bafed6a0ba9a62edb5f2ef78a8849b7615bd9433384171"},
+ {file = "yarl-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2941756754a10e799e5b87e2319bbec481ed0957421fba0e7b9fb1c11e40509f"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9611b83810a74a46be88847e0ea616794c406dbcb4e25405e52bff8f4bee2d0a"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cd7e35818d2328b679a13268d9ea505c85cd773572ebb7a0da7ccbca77b6a52e"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6b981316fcd940f085f646b822c2ff2b8b813cbd61281acad229ea3cbaabeb6b"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:688058e89f512fb7541cb85c2f149c292d3fa22f981d5a5453b40c5da49eb9e8"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56afb44a12b0864d17b597210d63a5b88915d680f6484d8d202ed68ade38673d"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:17931dfbb84ae18b287279c1f92b76a3abcd9a49cd69b92e946035cff06bcd20"},
+ {file = "yarl-1.17.2-cp312-cp312-win32.whl", hash = "sha256:ff8d95e06546c3a8c188f68040e9d0360feb67ba8498baf018918f669f7bc39b"},
+ {file = "yarl-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:4c840cc11163d3c01a9d8aad227683c48cd3e5be5a785921bcc2a8b4b758c4f3"},
+ {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3294f787a437cb5d81846de3a6697f0c35ecff37a932d73b1fe62490bef69211"},
+ {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f1e7fedb09c059efee2533119666ca7e1a2610072076926fa028c2ba5dfeb78c"},
+ {file = "yarl-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:da9d3061e61e5ae3f753654813bc1cd1c70e02fb72cf871bd6daf78443e9e2b1"},
+ {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91c012dceadc695ccf69301bfdccd1fc4472ad714fe2dd3c5ab4d2046afddf29"},
+ {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f11fd61d72d93ac23718d393d2a64469af40be2116b24da0a4ca6922df26807e"},
+ {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46c465ad06971abcf46dd532f77560181387b4eea59084434bdff97524444032"},
+ {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef6eee1a61638d29cd7c85f7fd3ac7b22b4c0fabc8fd00a712b727a3e73b0685"},
+ {file = "yarl-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4434b739a8a101a837caeaa0137e0e38cb4ea561f39cb8960f3b1e7f4967a3fc"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:752485cbbb50c1e20908450ff4f94217acba9358ebdce0d8106510859d6eb19a"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:17791acaa0c0f89323c57da7b9a79f2174e26d5debbc8c02d84ebd80c2b7bff8"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5c6ea72fe619fee5e6b5d4040a451d45d8175f560b11b3d3e044cd24b2720526"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db5ac3871ed76340210fe028f535392f097fb31b875354bcb69162bba2632ef4"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7a1606ba68e311576bcb1672b2a1543417e7e0aa4c85e9e718ba6466952476c0"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9bc27dd5cfdbe3dc7f381b05e6260ca6da41931a6e582267d5ca540270afeeb2"},
+ {file = "yarl-1.17.2-cp313-cp313-win32.whl", hash = "sha256:52492b87d5877ec405542f43cd3da80bdcb2d0c2fbc73236526e5f2c28e6db28"},
+ {file = "yarl-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:8e1bf59e035534ba4077f5361d8d5d9194149f9ed4f823d1ee29ef3e8964ace3"},
+ {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c556fbc6820b6e2cda1ca675c5fa5589cf188f8da6b33e9fc05b002e603e44fa"},
+ {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f44a4247461965fed18b2573f3a9eb5e2c3cad225201ee858726cde610daca"},
+ {file = "yarl-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a3ede8c248f36b60227eb777eac1dbc2f1022dc4d741b177c4379ca8e75571a"},
+ {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2654caaf5584449d49c94a6b382b3cb4a246c090e72453493ea168b931206a4d"},
+ {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d41c684f286ce41fa05ab6af70f32d6da1b6f0457459a56cf9e393c1c0b2217"},
+ {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2270d590997445a0dc29afa92e5534bfea76ba3aea026289e811bf9ed4b65a7f"},
+ {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18662443c6c3707e2fc7fad184b4dc32dd428710bbe72e1bce7fe1988d4aa654"},
+ {file = "yarl-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75ac158560dec3ed72f6d604c81090ec44529cfb8169b05ae6fcb3e986b325d9"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1fee66b32e79264f428dc8da18396ad59cc48eef3c9c13844adec890cd339db5"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:585ce7cd97be8f538345de47b279b879e091c8b86d9dbc6d98a96a7ad78876a3"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c019abc2eca67dfa4d8fb72ba924871d764ec3c92b86d5b53b405ad3d6aa56b0"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c6e659b9a24d145e271c2faf3fa6dd1fcb3e5d3f4e17273d9e0350b6ab0fe6e2"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:d17832ba39374134c10e82d137e372b5f7478c4cceeb19d02ae3e3d1daed8721"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bc3003710e335e3f842ae3fd78efa55f11a863a89a72e9a07da214db3bf7e1f8"},
+ {file = "yarl-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f5ffc6b7ace5b22d9e73b2a4c7305740a339fbd55301d52735f73e21d9eb3130"},
+ {file = "yarl-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:48e424347a45568413deec6f6ee2d720de2cc0385019bedf44cd93e8638aa0ed"},
+ {file = "yarl-1.17.2-py3-none-any.whl", hash = "sha256:dd7abf4f717e33b7487121faf23560b3a50924f80e4bef62b22dab441ded8f3b"},
+ {file = "yarl-1.17.2.tar.gz", hash = "sha256:753eaaa0c7195244c84b5cc159dc8204b7fd99f716f11198f999f2332a86b178"},
]
[package.dependencies]
idna = ">=2.0"
multidict = ">=4.0"
+propcache = ">=0.2.0"
[metadata]
lock-version = "2.0"
diff --git a/tools/devtool b/tools/devtool
index cfd746ee40c..c3b7b27ed98 100755
--- a/tools/devtool
+++ b/tools/devtool
@@ -417,7 +417,7 @@ cmd_help() {
echo " build_ci_artifacts [all|rootfs|kernels]"
echo " Builds the rootfs and guest kernel artifacts we use for our CI."
echo " Run './tools/devtool build_ci_artifacts help' for more details about the available commands."
- echo ""
+ echo ""
cat <]]
@@ -446,12 +446,14 @@ cmd_build() {
profile="debug"
libc="musl"
+
# Parse any command line args.
while [ $# -gt 0 ]; do
case "$1" in
"-h"|"--help") { cmd_help; exit 1; } ;;
"--debug") { profile="debug"; } ;;
"--release") { profile="release"; } ;;
+ "--rev") { shift; revision=$1; } ;;
"--ssh-keys")
shift
[[ -z "$1" ]] && \
@@ -489,16 +491,40 @@ cmd_build() {
extra_args="--volume $host_pub_key_path:$PUB_KEY_PATH:z \
--volume $host_priv_key_path:$PRIV_KEY_PATH:z"
+ workdir="$CTR_FC_ROOT_DIR"
+ if [ ! -z "$revision" ]; then
+ commitish="$revision"
+ if ! git cat-file -t "$commitish"; then commitish=origin/"$revision"; fi
+ branch_name=tmp-$commitish
+
+ tmp_dir=$(mktemp -d)
+
+ git branch $branch_name $commitish
+ git clone -b $branch_name . $tmp_dir
+ pushd $tmp_dir
+ workdir=$tmp_dir
+ extra_args="$extra_args --volume $tmp_dir:$tmp_dir:z"
+ fi
+
# Run the cargo build process inside the container.
# We don't need any special privileges for the build phase, so we run the
# container as the current user/group.
run_devctr \
--user "$(id -u):$(id -g)" \
- --workdir "$CTR_FC_ROOT_DIR" \
+ --workdir "$workdir" \
${extra_args} \
-- \
./tools/release.sh --libc $libc --profile $profile
ret=$?
+
+ if [ ! -z "$revision" ]; then
+ popd
+ git branch -D $branch_name
+ mkdir -p build/"$revision"
+ cp $tmp_dir/build/cargo_target/$(uname -m)-unknown-linux-$libc/$profile/* build/"$revision"
+ rm -rf $tmp_dir
+ fi
+
return $ret
}
@@ -536,14 +562,12 @@ ensure_ci_artifacts() {
# Fetch all the artifacts so they are local
say "Fetching CI artifacts from S3"
- S3_URL=s3://spec.ccfc.min/firecracker-ci/v1.10/$(uname -m)
+ S3_URL=s3://spec.ccfc.min/firecracker-ci/v1.11/$(uname -m)
ARTIFACTS=$MICROVM_IMAGES_DIR/$(uname -m)
if [ ! -d "$ARTIFACTS" ]; then
mkdir -pv $ARTIFACTS
aws s3 sync --no-sign-request "$S3_URL" "$ARTIFACTS"
- # fix permissions
- find "$ARTIFACTS" -type f -name "*.id_rsa" |xargs chmod -c 400
- find "$ARTIFACTS/firecracker" -type f |xargs chmod -c 755
+ cmd_sh "./tools/setup-ci-artifacts.sh"
fi
}
@@ -1167,7 +1191,7 @@ cmd_install() {
# Install the binaries
for binary in "${binaries[@]}"; do
say "Installing $binary in $install_path"
- install -m 755 "$( build_bin_path "$target" "$profile" "$binary" )" "$install_path"
+ install -m 755 -D -t "$install_path" "$( build_bin_path "$target" "$profile" "$binary" )"
done
}
diff --git a/tools/sandbox.py b/tools/sandbox.py
index fb15eb17fab..3cdcec345a7 100755
--- a/tools/sandbox.py
+++ b/tools/sandbox.py
@@ -68,11 +68,12 @@ def parse_byte_size(param):
else:
bins = get_firecracker_binaries()
-print("This step may take a while to compile Firecracker ...")
cpu_template = None
if args.cpu_template_path is not None:
cpu_template = json.loads(args.cpu_template_path.read_text())
vmfcty = MicroVMFactory(*bins)
+
+print(f"uvm with kernel {args.kernel} ...")
uvm = vmfcty.build(args.kernel, args.rootfs)
uvm.help.enable_console()
uvm.help.resize_disk(uvm.rootfs_file, args.rootfs_size)
@@ -85,3 +86,15 @@ def parse_byte_size(param):
print(cpu_template)
uvm.start()
uvm.get_all_metrics()
+
+kernel_dbg_dir = args.kernel.parent / "debug"
+kernel_dbg = kernel_dbg_dir / args.kernel.name
+print(f"uvm2 with kernel {kernel_dbg} ...")
+uvm2 = vmfcty.build(kernel_dbg, args.rootfs)
+uvm2.spawn()
+uvm2.add_net_iface()
+uvm2.basic_config(vcpu_count=args.vcpus, mem_size_mib=args.guest_mem_size // 2**20)
+uvm2.start()
+# trace-cmd needs this (DNS resolution?)
+uvm2.help.enable_ip_forwarding()
+files = uvm2.help.trace_cmd_guest(["-l", "read_msr"], cmd="sleep 5")
diff --git a/tools/setup-ci-artifacts.sh b/tools/setup-ci-artifacts.sh
new file mode 100755
index 00000000000..0d524658b51
--- /dev/null
+++ b/tools/setup-ci-artifacts.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+
+# fail if we encounter an error, uninitialized variable or a pipe breaks
+set -eu -o pipefail
+
+TOOLS_DIR=$(dirname $0)
+source "$TOOLS_DIR/functions"
+
+say "Setup CI artifacts"
+cd build/img/$(uname -m)
+
+say "Fix executable permissions"
+find "firecracker" -type f |xargs chmod -c 755
+
+say "Generate SSH key to connect from host"
+if [ ! -s id_rsa ]; then
+ ssh-keygen -f id_rsa -N ""
+fi
+
+for SQUASHFS in *.squashfs; do
+ say "Include SSH key in $SQUASHFS"
+ RSA=$(basename $SQUASHFS .squashfs).id_rsa
+ EXT4=$(basename $SQUASHFS .squashfs).ext4
+ [ -s $SQUASHFS.orig ] && continue
+ unsquashfs $SQUASHFS
+ mkdir -pv squashfs-root/root/.ssh
+ # copy the SSH key into the rootfs
+ if [ ! -s $RSA ]; then
+ # append SSH key to the squashfs image
+ cp -v id_rsa.pub squashfs-root/root/.ssh/authorized_keys
+ cp -v id_rsa $RSA
+ fi
+ # re-squash
+ mv -v $SQUASHFS $SQUASHFS.orig
+ mksquashfs squashfs-root $SQUASHFS -all-root -noappend -comp zstd
+
+ # Create rw ext4 image from ro squashfs
+ [ -f $EXT4 ] && continue
+ say "Converting $SQUASHFS to $EXT4"
+ truncate -s 400M $EXT4
+ mkfs.ext4 -F $EXT4 -d squashfs-root
+ rm -rf squashfs-root
+done
+
+say "Uncompress debuginfo files"
+find . -name "*.debug.gz" -print0 | xargs -P4 -0 -t -n1 gunzip
diff --git a/tools/test-popular-containers/build_rootfs.sh b/tools/test-popular-containers/build_rootfs.sh
index 547dd73af49..501197949f0 100755
--- a/tools/test-popular-containers/build_rootfs.sh
+++ b/tools/test-popular-containers/build_rootfs.sh
@@ -67,6 +67,6 @@ EOF
make_rootfs alpine:latest
make_rootfs ubuntu:22.04
-make_rootfs ubuntu:23.10
make_rootfs ubuntu:24.04
+make_rootfs ubuntu:24.10
# make_rootfs ubuntu:latest