diff --git a/changelog/bugfixes/2026-08-31-ip-kargs-parser.md b/changelog/bugfixes/2026-08-31-ip-kargs-parser.md new file mode 100644 index 00000000000..28cea4f931f --- /dev/null +++ b/changelog/bugfixes/2026-08-31-ip-kargs-parser.md @@ -0,0 +1 @@ +- Improved early boot `ip=` kernel command line handling by dropping Flatcar's custom parser in favour of systemd-network-generator. IPv6 and VLANs should work better, and it will no longer assign the given IP address to the loopback interface if you don't specify the device name. If you used `dhcp,dhcp6` for a dual stack configuration, you should now specify `any` instead. ([Flatcar#1708](https://github.com/flatcar/Flatcar/issues/1708), [Flatcar#1894](https://github.com/flatcar/Flatcar/issues/1894), [Flatcar#2002](https://github.com/flatcar/Flatcar/issues/2002)) diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-5.10.0-r1.ebuild b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-5.10.0-r2.ebuild similarity index 100% rename from sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-5.10.0-r1.ebuild rename to sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-5.10.0-r2.ebuild diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-9999.ebuild b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-9999.ebuild index 2b59f6d0f63..52ac2c91e1f 100644 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-9999.ebuild +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-9999.ebuild @@ -32,6 +32,7 @@ PATCHES=( "${FILESDIR}"/0001-Revert-remove-cl-legacy-feature.patch "${FILESDIR}"/0002-util-cmdline-Handle-the-cmdline-flags-as-list-of-sup.patch "${FILESDIR}"/0003-Cargo-reduce-binary-size-for-release-profile.patch + "${FILESDIR}"/0004-systemd-network-generator.patch ) src_unpack() { diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/files/0004-systemd-network-generator.patch b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/files/0004-systemd-network-generator.patch new file mode 100644 index 00000000000..b9f224162cb --- /dev/null +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/files/0004-systemd-network-generator.patch @@ -0,0 +1,283 @@ +From 33a1f0e050784f469f86ca14f2bf1411075db91e Mon Sep 17 00:00:00 2001 +From: Mathieu Tortuyaux +Date: Fri, 26 Jun 2026 12:11:42 +0200 +Subject: [PATCH 1/5] proxmoxve: explicit static IP configuration + +This costs nothing to append - dracut explodes this 'ip=' into variables[^1], +and downstream libraries might default to 'dhcp' if the 'autoconf' +variable is empty. + +[^1]: https://github.com/dracutdevs/dracut/blob/5d2bda46f4e75e85445ee4d3bd3f68bf966287b9/modules.d/40network/net-lib.sh#L541 + +Signed-off-by: Mathieu Tortuyaux +--- a/src/providers/proxmoxve/cloudconfig.rs ++++ b/src/providers/proxmoxve/cloudconfig.rs +@@ -199,13 +199,17 @@ impl MetadataProvider for ProxmoxVECloudConfig { + .find(|r| r.destination.is_ipv4() && r.destination.prefix() == 0) + { + kargs.push(format!( +- "ip={}::{}:{}", ++ "ip={}::{}:{}:::off", + network.ip(), + gateway.gateway, + network.mask() + )); + } else { +- kargs.push(format!("ip={}:::{}", network.ip(), network.mask())); ++ kargs.push(format!( ++ "ip={}:::{}:::off", ++ network.ip(), ++ network.mask() ++ )); + } + } + IpNetwork::V6(network) => { +@@ -215,13 +219,17 @@ impl MetadataProvider for ProxmoxVECloudConfig { + .find(|r| r.destination.is_ipv6() && r.destination.prefix() == 0) + { + kargs.push(format!( +- "ip={}::{}:{}", ++ "ip={}::{}:{}:::off", + network.ip(), + gateway.gateway, + network.prefix() + )); + } else { +- kargs.push(format!("ip={}:::{}", network.ip(), network.prefix())); ++ kargs.push(format!( ++ "ip={}:::{}:::off", ++ network.ip(), ++ network.prefix() ++ )); + } + } + } +-- +2.55.0 + + +From 9cf00f168e1c32fa16a89f8bc64e97ede2c7a948 Mon Sep 17 00:00:00 2001 +From: James Le Cuirot +Date: Mon, 6 Jul 2026 10:54:29 +0100 +Subject: [PATCH 2/5] initrd: Write an env file for systemd-network-generator + to consume + +systemd-network-generator parses /proc/cmdline or SYSTEMD_PROC_CMDLINE, +so the kargs we inject into Dracut's cmdline.d fragment are invisible to +it. Flatcar would like to switch from its own custom parser to the +generator's parser (and not Dracut's own). + +Signed-off-by: James Le Cuirot +--- a/src/initrd/mod.rs ++++ b/src/initrd/mod.rs +@@ -8,12 +8,25 @@ use crate::providers::proxmoxve::ProxmoxVEConfigDrive; + use crate::providers::vmware::VmwareProvider; + use crate::providers::MetadataProvider; + use anyhow::{Context, Result}; +-use std::fs::File; ++use std::fs::{self, File}; + use std::io::Write; ++use std::path::Path; + + /// Path to cmdline.d fragment for network kernel arguments. + static KARGS_PATH: &str = "/etc/cmdline.d/50-afterburn-network-kargs.conf"; + ++/// Path to the environment file consumed by systemd-network-generator. ++/// ++/// systemd-network-generator only parses /proc/cmdline (or the command line ++/// provided through the SYSTEMD_PROC_CMDLINE environment variable), so the ++/// kargs we inject into Dracut's cmdline.d fragment above are invisible to it. ++/// We therefore expose the augmented command line through this file, which a ++/// shipped generator drop-in references via EnvironmentFile=. ++static GENERATOR_ENV_PATH: &str = "/run/afterburn/network-generator.env"; ++ ++/// Path to the kernel command line. ++static PROC_CMDLINE_PATH: &str = "/proc/cmdline"; ++ + /// Fetch network kargs for the given provider. + pub(crate) fn fetch_network_kargs(provider: &str) -> Result> { + match provider { +@@ -23,10 +36,17 @@ pub(crate) fn fetch_network_kargs(provider: &str) -> Result> { + } + } + +-/// Write network kargs into a cmdline.d fragment. ++/// Write network kargs into a cmdline.d fragment and hand the augmented kernel ++/// command line to systemd-network-generator. + pub(crate) fn write_network_kargs(kargs: &str) -> Result<()> { +- let mut fragment_file = File::create(KARGS_PATH) +- .with_context(|| format!("failed to create file {KARGS_PATH:?}"))?; ++ write_cmdline_fragment(KARGS_PATH, kargs)?; ++ write_generator_env(GENERATOR_ENV_PATH, PROC_CMDLINE_PATH, kargs) ++} ++ ++/// Write network kargs into a Dracut cmdline.d fragment. ++fn write_cmdline_fragment(path: &str, kargs: &str) -> Result<()> { ++ let mut fragment_file = ++ File::create(path).with_context(|| format!("failed to create file {path:?}"))?; + + fragment_file + .write_all(kargs.as_bytes()) +@@ -37,3 +57,37 @@ pub(crate) fn write_network_kargs(kargs: &str) -> Result<()> { + + Ok(()) + } ++ ++/// Write the augmented kernel command line for systemd-network-generator. ++/// ++/// The generator does not read Dracut's cmdline.d fragments, so we combine the ++/// real kernel command line with the injected kargs and expose the result via ++/// SYSTEMD_PROC_CMDLINE in an environment file consumed by the generator's ++/// drop-in. ++fn write_generator_env(path: &str, proc_cmdline_path: &str, kargs: &str) -> Result<()> { ++ let kargs = kargs.trim(); ++ if kargs.is_empty() { ++ return Ok(()); ++ } ++ ++ let base = fs::read_to_string(proc_cmdline_path) ++ .with_context(|| format!("failed to read {proc_cmdline_path:?}"))?; ++ let base = base.trim(); ++ let cmdline = if base.is_empty() { ++ kargs.to_string() ++ } else { ++ format!("{base} {kargs}") ++ }; ++ ++ if let Some(parent) = Path::new(path).parent() { ++ fs::create_dir_all(parent) ++ .with_context(|| format!("failed to create directory {parent:?}"))?; ++ } ++ ++ let mut env_file = ++ File::create(path).with_context(|| format!("failed to create file {path:?}"))?; ++ writeln!(env_file, "SYSTEMD_PROC_CMDLINE={cmdline}") ++ .context("failed to write network generator environment file")?; ++ ++ Ok(()) ++} +-- +2.55.0 + + +From a9f3a8300471b60aaf982e59cf1ec099b83e3e60 Mon Sep 17 00:00:00 2001 +From: James Le Cuirot +Date: Tue, 18 Aug 2026 13:25:35 +0100 +Subject: [PATCH 3/5] initrd: Prevent ProxmoxVE from failing without a config + drive + +Signed-off-by: James Le Cuirot +--- a/src/initrd/mod.rs ++++ b/src/initrd/mod.rs +@@ -4,7 +4,7 @@ + //! services are configured, so it may not be able to use all usual metadata + //! fetcher. + +-use crate::providers::proxmoxve::ProxmoxVEConfigDrive; ++use crate::providers::proxmoxve; + use crate::providers::vmware::VmwareProvider; + use crate::providers::MetadataProvider; + use anyhow::{Context, Result}; +@@ -31,7 +31,7 @@ static PROC_CMDLINE_PATH: &str = "/proc/cmdline"; + pub(crate) fn fetch_network_kargs(provider: &str) -> Result> { + match provider { + "vmware" => VmwareProvider::try_new()?.rd_network_kargs(), +- "proxmoxve" => ProxmoxVEConfigDrive::try_new()?.rd_network_kargs(), ++ "proxmoxve" => proxmoxve::try_config_drive_else_leave()?.rd_network_kargs(), + _ => Ok(None), + } + } +-- +2.55.0 + + +From 0aad29f76fe4f3539356192263768ecb18ea4308 Mon Sep 17 00:00:00 2001 +From: James Le Cuirot +Date: Thu, 20 Aug 2026 18:36:21 +0100 +Subject: [PATCH 4/5] proxmoxve: Use ip=any rather than ip=dhcp,dhcp6 for dual + stack + +systemd-network-generator does not support multiple autoconf values, and +fixing this appears difficult. Even then, Dracut does not treat +`dhcp,dhcp6` in quite the same way that systemd and NetworkManager do. +It only tries IPv6 if IPv4 fails. + +As of Dracut 112, `any` is treated as IPv4-only, despite the name. +However, I have submitted https://github.com/dracut-ng/dracut/pull/2628 +to change this behaviour so that it is dual stack in the same manner as +systemd and NetworkManager. + +This would break Afterburn consumers relying on Dracut's network-legacy +in the meantime. However, FCOS has already migrated to NetworkManager, +and Flatcar is now migrating to systemd-network-manager. I'm not aware +of any other consumers. + +Signed-off-by: James Le Cuirot +--- a/src/providers/proxmoxve/cloudconfig.rs ++++ b/src/providers/proxmoxve/cloudconfig.rs +@@ -240,7 +240,7 @@ impl MetadataProvider for ProxmoxVECloudConfig { + match dhcp { + DhcpSetting::V4 => kargs.push("ip=dhcp".to_string()), + DhcpSetting::V6 => kargs.push("ip=dhcp6".to_string()), +- DhcpSetting::Both => kargs.push("ip=dhcp,dhcp6".to_string()), ++ DhcpSetting::Both => kargs.push("ip=any".to_string()), + } + } + +-- +2.55.0 + + +From ba688edc0b12bf59ed0204dbf5f45097a5db9671 Mon Sep 17 00:00:00 2001 +From: James Le Cuirot +Date: Fri, 21 Aug 2026 17:34:37 +0100 +Subject: [PATCH 5/5] proxmoxve: Fix dual stack network configuration + +Dual stack wasn't possible before because it would iterate over the +subnets, setting the type as either V4 or V6, but never combining them. + +Signed-off-by: James Le Cuirot +--- a/src/network.rs ++++ b/src/network.rs +@@ -153,6 +153,17 @@ impl DhcpSetting { + }; + setting.to_string() + } ++ ++ /// Combine DHCP settings, to easily merge [`Self::V4`] and [`Self::V6`] variants into ++ /// [`Self::Both`] where applicable. ++ pub fn merge(self, other: Self) -> Self { ++ use DhcpSetting::*; ++ match (self, other) { ++ (V4, V4) => V4, ++ (V6, V6) => V6, ++ _ => Both, ++ } ++ } + } + + impl Interface { +--- a/src/providers/proxmoxve/cloudconfig.rs ++++ b/src/providers/proxmoxve/cloudconfig.rs +@@ -399,10 +399,16 @@ impl ProxmoxVECloudNetworkConfigEntry { + } + + if subnet.subnet_type == "dhcp" || subnet.subnet_type == "dhcp4" { +- iface.dhcp = Some(DhcpSetting::V4) ++ iface.dhcp = iface ++ .dhcp ++ .map(|d| d.merge(DhcpSetting::V4)) ++ .or(Some(DhcpSetting::V4)) + } + if subnet.subnet_type == "dhcp6" { +- iface.dhcp = Some(DhcpSetting::V6) ++ iface.dhcp = iface ++ .dhcp ++ .map(|d| d.merge(DhcpSetting::V6)) ++ .or(Some(DhcpSetting::V6)) + } + if subnet.subnet_type == "ipv6_slaac" { + warn!("subnet type \"ipv6_slaac\" not supported, ignoring"); +-- +2.55.0 + diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/Manifest b/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/Manifest index 9d5cad89ec7..e7e498f1c37 100644 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/Manifest +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/Manifest @@ -1 +1 @@ -DIST coreos-init-0bf7e11f5b56b9f7adc2ddb3e4de885c531f3e7f.tar.gz 60406 BLAKE2B 3c1755aa50b340e0cf10fbc6bdee9644064409edf66c10779a34fd2ae30f27b11152c38331917a5dc79eeef3c92015a39f85efb66436c18c3482680ed22b1164 SHA512 f34802ffff59e971a812128c98729f0380277bb164b19525b171c9db77c1b538f6e5bd38d4e22e6150237770ee7324e53f19a8c6b4cdcfab3654d5269b739f77 +DIST coreos-init-3f8581468918512566a35974fe18479c7a353098.tar.gz 60356 BLAKE2B 8cab828dae68cf59a4cfd4aa12c190f2f33d0fe57089c3989317fee11f7cd7b79ca925d2095e508ec5327dd73d81e198e401cee58fd36b96989668c7eb4298fc SHA512 1b6311e5607dcac8b512cc0843b7b91764c256ff5b94bc06c5be4bbdf013c5e0d14570e50c51ad756db71d8ac2fa3068291b3fa942bd3b97051d142a940a7de3 diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/coreos-init-0.0.1-r206.ebuild b/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/coreos-init-0.0.1-r207.ebuild similarity index 100% rename from sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/coreos-init-0.0.1-r206.ebuild rename to sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/coreos-init-0.0.1-r207.ebuild diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/coreos-init-9999.ebuild b/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/coreos-init-9999.ebuild index 26f314c34a8..170723aa013 100644 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/coreos-init-9999.ebuild +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/coreos-init-9999.ebuild @@ -14,7 +14,7 @@ if [[ ${PV} == 9999 ]]; then EGIT_REPO_URI="https://github.com/flatcar/init.git" inherit git-r3 else - EGIT_VERSION="0bf7e11f5b56b9f7adc2ddb3e4de885c531f3e7f" # flatcar-master + EGIT_VERSION="3f8581468918512566a35974fe18479c7a353098" # flatcar-master SRC_URI="https://github.com/flatcar/init/archive/${EGIT_VERSION}.tar.gz -> ${PN}-${EGIT_VERSION}.tar.gz" S="${WORKDIR}/init-${EGIT_VERSION}" KEYWORDS="amd64 arm arm64 x86" diff --git a/sdk_container/src/third_party/coreos-overlay/coreos/user-patches/sys-kernel/dracut/050-change-network-dep-iscsi.patch b/sdk_container/src/third_party/coreos-overlay/coreos/user-patches/sys-kernel/dracut/050-change-network-dep-iscsi.patch deleted file mode 100644 index a097ebec8bd..00000000000 --- a/sdk_container/src/third_party/coreos-overlay/coreos/user-patches/sys-kernel/dracut/050-change-network-dep-iscsi.patch +++ /dev/null @@ -1,14 +0,0 @@ -As Flatcar uses the flatcar-network module, we need to replace it in the iscsi -module setup in order to enable iscsi support. - ---- a/modules.d/74iscsi/module-setup.sh -+++ b/modules.d/74iscsi/module-setup.sh -@@ -154,7 +154,7 @@ install_softiscsi() { - - # called by dracut - depends() { -- echo network rootfs-block initqueue -+ echo flatcar-network rootfs-block initqueue - } - - # called by dracut diff --git a/sdk_container/src/third_party/coreos-overlay/coreos/user-patches/sys-kernel/dracut/README.md b/sdk_container/src/third_party/coreos-overlay/coreos/user-patches/sys-kernel/dracut/README.md deleted file mode 100644 index 9e3f344bd4f..00000000000 --- a/sdk_container/src/third_party/coreos-overlay/coreos/user-patches/sys-kernel/dracut/README.md +++ /dev/null @@ -1,2 +0,0 @@ -`050-change-network-dep-iscsi.patch` is a Flatcar-specific dependency tweak to -use flatcar-network instead of network. diff --git a/sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/Manifest b/sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/Manifest index 7f1a87dfb2c..49d6f2a1ed9 100644 --- a/sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/Manifest +++ b/sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/Manifest @@ -1 +1 @@ -DIST bootengine-b92a1ca9f698bb155ffb7e9cccf83e27e0727817.tar.gz 34280 BLAKE2B 98ec74fac715e8d7c44a65b3b6a5c2d60fb073e77be5ad8f1a4c7cb31ee5dc2f942fe2d71d6c999a705322a38425a205b409f3d1a4c28807c985e010913f7e15 SHA512 66cfd5628f4eadab755ca3d809b66722dc5ae191ff4502b548de55dde14893da3889e9845abed5dfd576b2109c4c7c41262db47733c808aacdcb2cc2baf46f41 +DIST bootengine-7727ec78da72e700e8fa1ce2144cb2476448d186.tar.gz 31237 BLAKE2B bb98ec8dc8ae569c34b9bedc9196d7befa54df26177632e447804325a3ce3461d20573303872636c8c93ed9a731dca67faa8e25cfafb432fab82793c6932c8e2 SHA512 dfe5e741d2ed96397068c59619ae63b72180d18c29b280dd33b9f152c5e83d3b10a07217e67a95b671546aa1e3903fcdf9f65aa57b7baf6d6036a9e76db1479b diff --git a/sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/bootengine-0.0.38-r48.ebuild b/sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/bootengine-0.0.38-r49.ebuild similarity index 100% rename from sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/bootengine-0.0.38-r48.ebuild rename to sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/bootengine-0.0.38-r49.ebuild diff --git a/sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/bootengine-9999.ebuild b/sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/bootengine-9999.ebuild index cd8618b016f..e85982f0dd1 100644 --- a/sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/bootengine-9999.ebuild +++ b/sdk_container/src/third_party/coreos-overlay/sys-kernel/bootengine/bootengine-9999.ebuild @@ -10,7 +10,7 @@ if [[ ${PV} == 9999 ]]; then EGIT_REPO_URI="https://github.com/flatcar/bootengine.git" inherit git-r3 else - EGIT_VERSION="b92a1ca9f698bb155ffb7e9cccf83e27e0727817" # flatcar-master + EGIT_VERSION="7727ec78da72e700e8fa1ce2144cb2476448d186" # flatcar-master SRC_URI="https://github.com/flatcar/bootengine/archive/${EGIT_VERSION}.tar.gz -> ${PN}-${EGIT_VERSION}.tar.gz" S="${WORKDIR}/${PN}-${EGIT_VERSION}" KEYWORDS="amd64 arm arm64 x86" diff --git a/sdk_container/src/third_party/coreos-overlay/sys-kernel/coreos-kernel/coreos-kernel-6.12.105.ebuild b/sdk_container/src/third_party/coreos-overlay/sys-kernel/coreos-kernel/coreos-kernel-6.12.105.ebuild index 80f2e61a9fc..9826aa54454 100644 --- a/sdk_container/src/third_party/coreos-overlay/sys-kernel/coreos-kernel/coreos-kernel-6.12.105.ebuild +++ b/sdk_container/src/third_party/coreos-overlay/sys-kernel/coreos-kernel/coreos-kernel-6.12.105.ebuild @@ -33,6 +33,7 @@ DEPEND=" sys-apps/busybox sys-apps/coreutils sys-apps/findutils + sys-apps/gptfdisk sys-apps/grep sys-apps/hwdata sys-apps/ignition:=