From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id 18EBD1FF0E3 for ; Tue, 27 Oct 2026 10:30:56 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 6946021616; Tue, 27 Oct 2026 10:30:55 +0100 (CET) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792958669; x=1793563469; h=content-type:to:subject:message-id:date:references:in-reply-to:from :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=5xaclBx5uNwFfA7KTnTr+TKf/dmsBkaCYJ6WSojKEOo=; b=VhbR4RY2ywqbq5xurZXrotdfN9kxq/zvanY9cXVwxS9SfFSv4XfqvfmbKC08PnduI1 O9VDy8RXTcprgHCXpYrcmmuxECc5eaYtX6FHqF9IYXR8mfdpajk0CCU0LNDlWUEgHEl3 FnvGN3pGKH+pI3jXRFrpMVhSjJ+5CWHRlq/GGTP1Ae1oDwzfeWEjy/JriJIT/csEPpxc qvc2q+yF3A1hF2hXAOHRmdgGug3uuwb71iovEpk9NWe8GTYOkJMHUSZLansJwit+jHm8 uYQC4HIHH58TurFFDYRBTSM3oiuX+AADkcsHGoLT6KnJy0u+Jznx5BM/O50WR414emDr Z/JA== X-Gm-Message-State: AFq9FYJbxHhlMOFtikc5dFSQEhvnFH3eFiOZ1Ddyp1NIIE4lSA7PMokq oEbuZzoikH7jg2iavlUWFFQEQ6RrsjezvPVVBTl4CZuqq9+gu8nFQIQMdx8eztHY X-Gm-Gg: AYBFou3hO2EFYXVo15IkRxO9VtzoViEyI/fyahDtYgjRvYmFJldqSMfs8DbRNPh0ZeM GWtlHZO8jBpoO2aZa2m5/e0EPZNkxQBiYMySBKmLV6w8oFYD/8L65nVPWlMaGvrt3RPMcChUrTu M9hqYHDGxkH5H3hltUOS87rBPctAmkjqefd0DSLrt8FAPQGWYsSLS+IooNtoB+Tp1RIlq0TrOh2 UgGcTC+Xqcf4fSgrprJT10wd84OENmS4NpTzkOl/JVbyTSYis/qfXAg2Xqt9wLJHrJXfNVzrNiU zOhFsJpJWhn4/6Jf3nXtwHxf/7tXq8Jjj7lbgdA3F/nT/P36hXDhIWV7SXSSLB4PF6R4JrFPI7u +3TGeGco+lC6K7SP470lQ8ojOuYvgv8XfQlBAh8qIuuL86pDys0FUSAkvRIwGxGLLf/+3y4gf5z G9p0IAslnA6p/uuTL2DTLGhXYEwbrKghJEF7Y+vg9xLTrlngquNe2E6UxlBdj0ZHmh3UYYERJzj 1wgm1LiRzAo5cuoKwZAx0x1B41cijCDtaK32RKqsD6h71J/UGFw19Dg6qhEqD7VLFbuYO5Nf4OB BZ73N7okHqs= X-Received: by 2002:a05:6830:230a:b0:822:e7cb:3e8b with SMTP id 46e09a7af769-850ff57d48amr3893817a34.30.1792958302838; Sun, 25 Oct 2026 12:58:22 -0700 (PDT) X-Received: by 2002:a05:6808:1205:b0:4fc:5e91:5377 with SMTP id 5614622812f47-55c0038d63fmr3138748b6e.59.1792958302185; Sun, 25 Oct 2026 12:58:22 -0700 (PDT) MIME-Version: 1.0 From: i@leaskh.com In-Reply-To: References: Date: Sun, 25 Oct 2026 14:58:20 -0500 X-Gmail-Original-Message-ID: X-Gm-Features: AclHuK_4uVYxGsOHYSNJWl9DjUwNU_kCn3PlFkHhkyXtclZlLS39TNLn1ZwZjEk Message-ID: Subject: [PATCH proxmox 1/2] fix #8227: network api: support encapsulated bond hash policies To: pbs-devel@lists.proxmox.com Content-Type: text/plain; charset="UTF-8" X-SPAM-LEVEL: Spam detection results: 0 DMARC_NONE 0.1 DMARC none policy FREEMAIL_FORGED_FROMDOMAIN 0.001 2nd level domains in From and EnvelopeFrom freemail headers are different FREEMAIL_FROM 0.001 Sender email is commonly abused enduser mail provider HEADER_FROM_DIFFERENT_DOMAINS 0.25 From and EnvelopeFrom 2nd level mail domains are different KAM_DMARC_NONE 0.25 DKIM has Failed or SPF has failed on the message and the domain has a DMARC none policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_NONE -0.0001 Sender listed at https://www.dnswl.org/, no trust RCVD_IN_MSPIKE_H2 0.001 Average reputation (+2) SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record X-MailFrom: leaskh@gmail.com X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation Message-ID-Hash: ZZ76FSQ5VFWJ6LHWJ6GPG2O7KMYXPYIP X-Message-ID-Hash: ZZ76FSQ5VFWJ6LHWJ6GPG2O7KMYXPYIP X-Mailman-Approved-At: Tue, 27 Oct 2026 10:30:47 +0100 X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Leask Wong Linux and ifupdown2 accept encap2+3 and encap3+4, but the shared network API rejects both while reading interfaces configuration. This prevents PBS from loading its complete network configuration page. Extend the enum, generated schema and Display implementation without changing existing serialized values. Add serde/schema validation and configuration round-trip coverage for both bond modes and spellings. The regression tests fail against the previous enum. With the fix, all 30 network API library tests pass on Linux with the impl feature. Signed-off-by: Leask Wong --- proxmox-network-api/src/api_types.rs | 48 ++++++++++++++++++++ proxmox-network-api/src/config/parser.rs | 58 ++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/proxmox-network-api/src/api_types.rs b/proxmox-network-api/src/api_types.rs index f2467f1..9e392bc 100644 --- a/proxmox-network-api/src/api_types.rs +++ b/proxmox-network-api/src/api_types.rs @@ -92,6 +92,12 @@ pub enum BondXmitHashPolicy { /// Layer 3+4 #[serde(rename = "layer3+4")] Layer3_4 = 2, + /// Encapsulated Layer 2+3 + #[serde(rename = "encap2+3")] + Encap2_3 = 3, + /// Encapsulated Layer 3+4 + #[serde(rename = "encap3+4")] + Encap3_4 = 4, } impl fmt::Display for BondXmitHashPolicy { @@ -100,10 +106,52 @@ impl fmt::Display for BondXmitHashPolicy { BondXmitHashPolicy::Layer2 => "layer2", BondXmitHashPolicy::Layer2_3 => "layer2+3", BondXmitHashPolicy::Layer3_4 => "layer3+4", + BondXmitHashPolicy::Encap2_3 => "encap2+3", + BondXmitHashPolicy::Encap3_4 => "encap3+4", }) } } +#[cfg(test)] +mod bond_hash_policy_tests { + use super::*; + use proxmox_schema::ApiType; + + #[test] + fn bond_hash_policy_schema_and_serde_round_trip() -> Result<(), Error> { + for name in ["layer2", "layer2+3", "layer3+4", "encap2+3", "encap3+4"] { + let value = serde_json::Value::String(name.to_string()); + let policy: BondXmitHashPolicy = serde_json::from_value(value.clone())?; + + assert_eq!(policy.to_string(), name); + assert_eq!(serde_json::to_value(policy)?, value); + assert_eq!( + BondXmitHashPolicy::API_SCHEMA.parse_simple_value(name)?, + value + ); + } + + Ok(()) + } + + #[test] + fn bond_hash_policy_rejects_invalid_values() { + for name in ["encap3-4", "encap5+6", "", "4"] { + assert!( + serde_json::from_value::(serde_json::Value::String( + name.to_string() + )) + .is_err() + ); + assert!( + BondXmitHashPolicy::API_SCHEMA + .parse_simple_value(name) + .is_err() + ); + } + } +} + #[api()] #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] diff --git a/proxmox-network-api/src/config/parser.rs b/proxmox-network-api/src/config/parser.rs index 71c9ec0..2851b8c 100644 --- a/proxmox-network-api/src/config/parser.rs +++ b/proxmox-network-api/src/config/parser.rs @@ -657,6 +657,64 @@ mod test { use super::*; + #[test] + fn test_bond_hash_policy_config_round_trip() -> Result<(), Error> { + for mode in ["802.3ad", "balance-xor"] { + for keyword in ["bond-xmit-hash-policy", "bond_xmit_hash_policy"] { + for policy in ["layer2", "layer2+3", "layer3+4", "encap2+3", "encap3+4"] { + let input = format!( + "iface enp1s0 inet manual\n\n\ + iface enp2s0 inet manual\n\n\ + iface bond0 inet manual\n\ + \tbond-mode {mode}\n\ + \tbond-slaves enp1s0 enp2s0\n\ + \t{keyword} {policy}\n\n\ + iface vmbr0 inet manual\n\ + \tbridge-ports bond0\n" + ); + let mut parser = NetworkParser::new(input.as_bytes()); + let config = parser.parse_interfaces(None)?; + let bond = config.lookup("bond0")?; + let expected = bond.bond_xmit_hash_policy; + + assert_eq!(expected.unwrap().to_string(), policy); + assert_eq!( + config.lookup("vmbr0")?.interface_type, + NetworkInterfaceType::Bridge + ); + + let output = String::try_from(config)?; + let mut parser = NetworkParser::new(output.as_bytes()); + let restored = parser.parse_interfaces(None)?; + + assert_eq!(restored.lookup("bond0")?.bond_xmit_hash_policy, expected); + assert_eq!( + restored.lookup("vmbr0")?.bridge_ports, + Some(vec!["bond0".into()]) + ); + assert_eq!(String::try_from(restored)?, output); + } + } + } + + Ok(()) + } + + #[test] + fn test_invalid_bond_hash_policy_reports_line() { + let input = "iface bond0 inet manual\n\ + \tbond-mode 802.3ad\n\ + \tbond-xmit-hash-policy encap5+6\n"; + let mut parser = NetworkParser::new(input.as_bytes()); + let error = parser.parse_interfaces(None).unwrap_err().to_string(); + + assert!(error.contains("line 3:"), "{error}"); + assert!( + error.contains("invalid bond_xmit_hash_policy 'encap5+6'"), + "{error}" + ); + } + #[test] fn test_network_config_create_lo_1() -> Result<(), Error> { let input = ""; -- 2.56.0 On Sun, 25 Oct 2026 14:57:50 -0500, i@leaskh.com wrote: > Hi, > > This series fixes PBS bug #8227: > https://bugzilla.proxmox.com/show_bug.cgi?id=8227 > > An operational Linux 802.3ad bond using encap3+4 makes PBS reject > /etc/network/interfaces and prevents the Network Interfaces list from > loading. Linux and ifupdown2 support the policy; the shared Rust API's > enum and the shared UI selector currently list only the three layer* > policies. > > Patch 1/2 targets proxmox.git and adds encap2+3 and encap3+4 to the enum, > generated schema and Display implementation. It includes validation and > configuration round-trip regression tests. Existing values and invalid > name validation are preserved. > > Patch 2/2 targets proxmox-widget-toolkit.git and exposes the two policies > in the shared selector. It is the companion UI change to patch 1/2. > > Validation: > - Native Linux x86_64: all 30 network API library tests pass with the > impl feature. Against the old enum, the two new acceptance/round-trip > tests fail with the expected policy rejection. > - Round trips cover five policies, both 802.3ad/balance-xor modes and > both keyword spellings, including an unrelated following bridge. > - JavaScript syntax and selector-definition runtime checks pass. > - Rust formatting, whitespace and patch application checks pass. > > The Linux build used a disposable workspace restricted to ten local > crates, including the network API, omitting non-target dev resolution. > The build setup did not alter library sources. Dependencies came from > crates.io and OpenSSL headers were unpacked privately. This is not a > full Debian package build or an end-to-end GUI test, and no running > host's network configuration was changed. > > I emailed my Individual CLA privately to office@proxmox.com today, > identifying Leask Wong as my Git author identity. > CLA registration has not yet been verified. > > The existing Bugzilla attachments contain the same code changes: > https://bugzilla.proxmox.com/attachment.cgi?id=2193 > https://bugzilla.proxmox.com/attachment.cgi?id=2194 > These mail patches additionally include the requested sign-off trailer. > > Please review, and let me know if any changes are needed. > > Thanks, > Leask