From 9d94142e2f16bb200ab998bbd4511993752ca4ae Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Mon, 1 Jun 2026 09:37:35 +0800 Subject: [PATCH 1/2] bond: align FromStr/Display strings with iproute2 - Change BondXmitHashPolicy Display/FromStr strings to match iproute2: "layer34"->"layer3+4", "layer23"->"layer2+3", "encap23"->"encap2+3", "encap34"->"encap3+4", "vlan-src-mac"->"vlan+srcmac" - Add BOND_AD_ACTOR_PORT_PRIO constant and ActorPortPrio variant to BondAdSelect with Display/FromStr support Unit tests for both BondXmitHashPolicy and BondAdSelect FromStr are updated. Signed-off-by: Gris Ge --- src/link/link_info/bond.rs | 26 ++++++++++++++++---------- src/link/tests/bond.rs | 14 +++++++++----- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/link/link_info/bond.rs b/src/link/link_info/bond.rs index 30156f7f..bd191191 100644 --- a/src/link/link_info/bond.rs +++ b/src/link/link_info/bond.rs @@ -436,11 +436,11 @@ impl std::fmt::Display for BondXmitHashPolicy { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let kernel_name = match self { BondXmitHashPolicy::Layer2 => "layer2", - BondXmitHashPolicy::Layer34 => "layer34", - BondXmitHashPolicy::Layer23 => "layer23", - BondXmitHashPolicy::Encap23 => "encap23", - BondXmitHashPolicy::Encap34 => "encap34", - BondXmitHashPolicy::VlanSrcMac => "vlan-src-mac", + BondXmitHashPolicy::Layer34 => "layer3+4", + BondXmitHashPolicy::Layer23 => "layer2+3", + BondXmitHashPolicy::Encap23 => "encap2+3", + BondXmitHashPolicy::Encap34 => "encap3+4", + BondXmitHashPolicy::VlanSrcMac => "vlan+srcmac", BondXmitHashPolicy::Other(d) => { return write!(f, "unknown-variant ({d})") } @@ -455,11 +455,11 @@ impl std::str::FromStr for BondXmitHashPolicy { fn from_str(s: &str) -> Result { Ok(match s { "layer2" => Self::Layer2, - "layer34" => Self::Layer34, - "layer23" => Self::Layer23, - "encap23" => Self::Encap23, - "encap34" => Self::Encap34, - "vlan-src-mac" => Self::VlanSrcMac, + "layer3+4" => Self::Layer34, + "layer2+3" => Self::Layer23, + "encap2+3" => Self::Encap23, + "encap3+4" => Self::Encap34, + "vlan+srcmac" => Self::VlanSrcMac, _ => { return Err(DecodeError::from(format!( "unknown bond xmit hash policy: {s}" @@ -723,6 +723,7 @@ impl From for u8 { const BOND_AD_STABLE: u8 = 0; const BOND_AD_BANDWIDTH: u8 = 1; const BOND_AD_COUNT: u8 = 2; +const BOND_AD_ACTOR_PORT_PRIO: u8 = 3; #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[non_exhaustive] @@ -730,6 +731,7 @@ pub enum BondAdSelect { Stable, Bandwidth, Count, + ActorPortPrio, Other(u8), } @@ -739,6 +741,7 @@ impl From for BondAdSelect { BOND_AD_STABLE => Self::Stable, BOND_AD_BANDWIDTH => Self::Bandwidth, BOND_AD_COUNT => Self::Count, + BOND_AD_ACTOR_PORT_PRIO => Self::ActorPortPrio, _ => Self::Other(d), } } @@ -750,6 +753,7 @@ impl From for u8 { BondAdSelect::Stable => BOND_AD_STABLE, BondAdSelect::Bandwidth => BOND_AD_BANDWIDTH, BondAdSelect::Count => BOND_AD_COUNT, + BondAdSelect::ActorPortPrio => BOND_AD_ACTOR_PORT_PRIO, BondAdSelect::Other(d) => d, } } @@ -761,6 +765,7 @@ impl std::fmt::Display for BondAdSelect { BondAdSelect::Stable => "stable", BondAdSelect::Bandwidth => "bandwidth", BondAdSelect::Count => "count", + BondAdSelect::ActorPortPrio => "actor_port_prio", BondAdSelect::Other(d) => { return write!(f, "unknown-variant ({d})") } @@ -777,6 +782,7 @@ impl std::str::FromStr for BondAdSelect { "stable" => Self::Stable, "bandwidth" => Self::Bandwidth, "count" => Self::Count, + "actor_port_prio" => Self::ActorPortPrio, _ => { return Err(DecodeError::from(format!( "unknown bond ad select: {s}" diff --git a/src/link/tests/bond.rs b/src/link/tests/bond.rs index 62d50da5..bee780e2 100644 --- a/src/link/tests/bond.rs +++ b/src/link/tests/bond.rs @@ -276,13 +276,13 @@ fn test_bond_primary_reselect_from_str() { fn test_bond_xmit_hash_policy_from_str() { use std::str::FromStr; assert_eq!(BondXmitHashPolicy::Layer2, "layer2".parse().unwrap()); - assert_eq!(BondXmitHashPolicy::Layer34, "layer34".parse().unwrap()); - assert_eq!(BondXmitHashPolicy::Layer23, "layer23".parse().unwrap()); - assert_eq!(BondXmitHashPolicy::Encap23, "encap23".parse().unwrap()); - assert_eq!(BondXmitHashPolicy::Encap34, "encap34".parse().unwrap()); + assert_eq!(BondXmitHashPolicy::Layer34, "layer3+4".parse().unwrap()); + assert_eq!(BondXmitHashPolicy::Layer23, "layer2+3".parse().unwrap()); + assert_eq!(BondXmitHashPolicy::Encap23, "encap2+3".parse().unwrap()); + assert_eq!(BondXmitHashPolicy::Encap34, "encap3+4".parse().unwrap()); assert_eq!( BondXmitHashPolicy::VlanSrcMac, - "vlan-src-mac".parse().unwrap() + "vlan+srcmac".parse().unwrap() ); assert!(BondXmitHashPolicy::from_str("bogus").is_err()); } @@ -310,5 +310,9 @@ fn test_bond_ad_select_from_str() { assert_eq!(BondAdSelect::Stable, "stable".parse().unwrap()); assert_eq!(BondAdSelect::Bandwidth, "bandwidth".parse().unwrap()); assert_eq!(BondAdSelect::Count, "count".parse().unwrap()); + assert_eq!( + BondAdSelect::ActorPortPrio, + "actor_port_prio".parse().unwrap() + ); assert!(BondAdSelect::from_str("bogus").is_err()); } From 099ba90f73ab5f107f7dd924fdf277997e79bfbf Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Mon, 1 Jun 2026 10:22:16 +0800 Subject: [PATCH 2/2] bond: add FromStr/Display for BondLacpRate Add FromStr and Display trait implementations for BondLacpRate using "slow"/"fast" strings. Unit test included. Signed-off-by: Gris Ge --- src/link/link_info/bond.rs | 26 ++++++++++++++++++++++++++ src/link/tests/bond.rs | 8 ++++++++ 2 files changed, 34 insertions(+) diff --git a/src/link/link_info/bond.rs b/src/link/link_info/bond.rs index bd191191..085753ec 100644 --- a/src/link/link_info/bond.rs +++ b/src/link/link_info/bond.rs @@ -720,6 +720,32 @@ impl From for u8 { } } +impl std::fmt::Display for BondLacpRate { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BondLacpRate::Slow => f.write_str("slow"), + BondLacpRate::Fast => f.write_str("fast"), + BondLacpRate::Other(v) => write!(f, "{v}"), + } + } +} + +impl std::str::FromStr for BondLacpRate { + type Err = DecodeError; + + fn from_str(s: &str) -> Result { + Ok(match s { + "slow" => Self::Slow, + "fast" => Self::Fast, + _ => { + return Err(DecodeError::from(format!( + "unknown bond lacp rate: {s}" + ))) + } + }) + } +} + const BOND_AD_STABLE: u8 = 0; const BOND_AD_BANDWIDTH: u8 = 1; const BOND_AD_COUNT: u8 = 2; diff --git a/src/link/tests/bond.rs b/src/link/tests/bond.rs index bee780e2..f07c1f5e 100644 --- a/src/link/tests/bond.rs +++ b/src/link/tests/bond.rs @@ -316,3 +316,11 @@ fn test_bond_ad_select_from_str() { ); assert!(BondAdSelect::from_str("bogus").is_err()); } + +#[test] +fn test_bond_lacp_rate_from_str() { + use std::str::FromStr; + assert_eq!(BondLacpRate::Slow, "slow".parse().unwrap()); + assert_eq!(BondLacpRate::Fast, "fast".parse().unwrap()); + assert!(BondLacpRate::from_str("bogus").is_err()); +}