Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions src/link/link_info/bond.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,27 @@ impl std::fmt::Display for BondMode {
}
}

impl std::str::FromStr for BondMode {
type Err = DecodeError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"balance-rr" => Self::BalanceRr,
"active-backup" => Self::ActiveBackup,
"balance-xor" => Self::BalanceXor,
"broadcast" => Self::Broadcast,
"802.3ad" => Self::Ieee8023Ad,
"balance-tlb" => Self::BalanceTlb,
"balance-alb" => Self::BalanceAlb,
_ => {
return Err(DecodeError::from(format!(
"unknown bond mode: {s}"
)))
}
})
}
Comment on lines +230 to +245

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using Ok(match s { ... _ => return Err(...) }) is non-idiomatic in Rust. It is cleaner and more idiomatic to match directly to Result<Self, Self::Err> by wrapping each successful arm in Ok and the fallback arm in Err.

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "balance-rr" => Ok(Self::BalanceRr),
            "active-backup" => Ok(Self::ActiveBackup),
            "balance-xor" => Ok(Self::BalanceXor),
            "broadcast" => Ok(Self::Broadcast),
            "802.3ad" => Ok(Self::Ieee8023Ad),
            "balance-tlb" => Ok(Self::BalanceTlb),
            "balance-alb" => Ok(Self::BalanceAlb),
            _ => Err(DecodeError::from(format!("unknown bond mode: {s}"))),
        }
    }

}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
#[non_exhaustive]
pub enum BondArpValidate {
Expand Down Expand Up @@ -286,6 +307,27 @@ impl std::fmt::Display for BondArpValidate {
}
}

impl std::str::FromStr for BondArpValidate {
type Err = DecodeError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"none" => Self::None,
"active" => Self::Active,
"backup" => Self::Backup,
"all" => Self::All,
"filter" => Self::Filter,
"filter_active" => Self::FilterActive,
"filter_backup" => Self::FilterBackup,
_ => {
return Err(DecodeError::from(format!(
"unknown bond arp validate: {s}"
)))
}
})
}
Comment on lines +313 to +328

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using Ok(match s { ... _ => return Err(...) }) is non-idiomatic in Rust. It is cleaner and more idiomatic to match directly to Result<Self, Self::Err> by wrapping each successful arm in Ok and the fallback arm in Err.

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "none" => Ok(Self::None),
            "active" => Ok(Self::Active),
            "backup" => Ok(Self::Backup),
            "all" => Ok(Self::All),
            "filter" => Ok(Self::Filter),
            "filter_active" => Ok(Self::FilterActive),
            "filter_backup" => Ok(Self::FilterBackup),
            _ => Err(DecodeError::from(format!("unknown bond arp validate: {s}"))),
        }
    }

}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
#[non_exhaustive]
pub enum BondPrimaryReselect {
Expand Down Expand Up @@ -332,6 +374,23 @@ impl std::fmt::Display for BondPrimaryReselect {
}
}

impl std::str::FromStr for BondPrimaryReselect {
type Err = DecodeError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"always" => Self::Always,
"better" => Self::Better,
"failure" => Self::Failure,
_ => {
return Err(DecodeError::from(format!(
"unknown bond primary reselect: {s}"
)))
}
})
}
Comment on lines +380 to +391

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using Ok(match s { ... _ => return Err(...) }) is non-idiomatic in Rust. It is cleaner and more idiomatic to match directly to Result<Self, Self::Err> by wrapping each successful arm in Ok and the fallback arm in Err.

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "always" => Ok(Self::Always),
            "better" => Ok(Self::Better),
            "failure" => Ok(Self::Failure),
            _ => Err(DecodeError::from(format!("unknown bond primary reselect: {s}"))),
        }
    }

}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
#[non_exhaustive]
pub enum BondXmitHashPolicy {
Expand Down Expand Up @@ -390,6 +449,26 @@ impl std::fmt::Display for BondXmitHashPolicy {
}
}

impl std::str::FromStr for BondXmitHashPolicy {
type Err = DecodeError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"layer2" => Self::Layer2,
"layer34" => Self::Layer34,
"layer23" => Self::Layer23,
"encap23" => Self::Encap23,
"encap34" => Self::Encap34,
"vlan-src-mac" => Self::VlanSrcMac,
_ => {
return Err(DecodeError::from(format!(
"unknown bond xmit hash policy: {s}"
)))
}
})
}
Comment on lines +455 to +469

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using Ok(match s { ... _ => return Err(...) }) is non-idiomatic in Rust. It is cleaner and more idiomatic to match directly to Result<Self, Self::Err> by wrapping each successful arm in Ok and the fallback arm in Err.

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "layer2" => Ok(Self::Layer2),
            "layer34" => Ok(Self::Layer34),
            "layer23" => Ok(Self::Layer23),
            "encap23" => Ok(Self::Encap23),
            "encap34" => Ok(Self::Encap34),
            "vlan-src-mac" => Ok(Self::VlanSrcMac),
            _ => Err(DecodeError::from(format!("unknown bond xmit hash policy: {s}"))),
        }
    }

}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
#[non_exhaustive]
pub enum BondArpAllTargets {
Expand Down Expand Up @@ -432,6 +511,22 @@ impl std::fmt::Display for BondArpAllTargets {
}
}

impl std::str::FromStr for BondArpAllTargets {
type Err = DecodeError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"any" => Self::Any,
"all" => Self::All,
_ => {
return Err(DecodeError::from(format!(
"unknown bond arp all targets: {s}"
)))
}
})
}
Comment on lines +517 to +527

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using Ok(match s { ... _ => return Err(...) }) is non-idiomatic in Rust. It is cleaner and more idiomatic to match directly to Result<Self, Self::Err> by wrapping each successful arm in Ok and the fallback arm in Err.

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "any" => Ok(Self::Any),
            "all" => Ok(Self::All),
            _ => Err(DecodeError::from(format!("unknown bond arp all targets: {s}"))),
        }
    }

}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
#[non_exhaustive]
pub enum BondFailOverMac {
Expand Down Expand Up @@ -478,6 +573,23 @@ impl std::fmt::Display for BondFailOverMac {
}
}

impl std::str::FromStr for BondFailOverMac {
type Err = DecodeError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"none" => Self::None,
"active" => Self::Active,
"follow" => Self::Follow,
_ => {
return Err(DecodeError::from(format!(
"unknown bond fail over mac: {s}"
)))
}
})
}
Comment on lines +579 to +590

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using Ok(match s { ... _ => return Err(...) }) is non-idiomatic in Rust. It is cleaner and more idiomatic to match directly to Result<Self, Self::Err> by wrapping each successful arm in Ok and the fallback arm in Err.

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "none" => Ok(Self::None),
            "active" => Ok(Self::Active),
            "follow" => Ok(Self::Follow),
            _ => Err(DecodeError::from(format!("unknown bond fail over mac: {s}"))),
        }
    }

}

// Some attributes (ARP_IP_TARGET, NS_IP6_TARGET) contain a nested
// list of IP addresses, where each element uses the index as NLA kind
// and the address as value. InfoBond exposes vectors of IP addresses,
Expand Down Expand Up @@ -643,6 +755,37 @@ impl From<BondAdSelect> for u8 {
}
}

impl std::fmt::Display for BondAdSelect {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let kernel_name = match self {
BondAdSelect::Stable => "stable",
BondAdSelect::Bandwidth => "bandwidth",
BondAdSelect::Count => "count",
BondAdSelect::Other(d) => {
return write!(f, "unknown-variant ({d})")
}
};
f.write_str(kernel_name)
}
}

impl std::str::FromStr for BondAdSelect {
type Err = DecodeError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"stable" => Self::Stable,
"bandwidth" => Self::Bandwidth,
"count" => Self::Count,
_ => {
return Err(DecodeError::from(format!(
"unknown bond ad select: {s}"
)))
}
})
}
Comment on lines +775 to +786

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using Ok(match s { ... _ => return Err(...) }) is non-idiomatic in Rust. It is cleaner and more idiomatic to match directly to Result<Self, Self::Err> by wrapping each successful arm in Ok and the fallback arm in Err.

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "stable" => Ok(Self::Stable),
            "bandwidth" => Ok(Self::Bandwidth),
            "count" => Ok(Self::Count),
            _ => Err(DecodeError::from(format!("unknown bond ad select: {s}"))),
        }
    }

}

#[derive(Debug, PartialEq, Eq, Clone)]
#[non_exhaustive]
pub enum InfoBond {
Expand Down
82 changes: 82 additions & 0 deletions src/link/tests/bond.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,85 @@ fn test_bond_arp_validate() {

assert_eq!(raw, buf);
}

#[test]
fn test_bond_mode_from_str() {
use std::str::FromStr;
assert_eq!(BondMode::BalanceRr, "balance-rr".parse().unwrap());
assert_eq!(BondMode::ActiveBackup, "active-backup".parse().unwrap());
assert_eq!(BondMode::BalanceXor, "balance-xor".parse().unwrap());
assert_eq!(BondMode::Broadcast, "broadcast".parse().unwrap());
assert_eq!(BondMode::Ieee8023Ad, "802.3ad".parse().unwrap());
assert_eq!(BondMode::BalanceTlb, "balance-tlb".parse().unwrap());
assert_eq!(BondMode::BalanceAlb, "balance-alb".parse().unwrap());
assert!(BondMode::from_str("bogus").is_err());
}

#[test]
fn test_bond_arp_validate_from_str() {
use std::str::FromStr;
assert_eq!(BondArpValidate::None, "none".parse().unwrap());
assert_eq!(BondArpValidate::Active, "active".parse().unwrap());
assert_eq!(BondArpValidate::Backup, "backup".parse().unwrap());
assert_eq!(BondArpValidate::All, "all".parse().unwrap());
assert_eq!(BondArpValidate::Filter, "filter".parse().unwrap());
assert_eq!(
BondArpValidate::FilterActive,
"filter_active".parse().unwrap()
);
assert_eq!(
BondArpValidate::FilterBackup,
"filter_backup".parse().unwrap()
);
assert!(BondArpValidate::from_str("bogus").is_err());
}

#[test]
fn test_bond_primary_reselect_from_str() {
use std::str::FromStr;
assert_eq!(BondPrimaryReselect::Always, "always".parse().unwrap());
assert_eq!(BondPrimaryReselect::Better, "better".parse().unwrap());
assert_eq!(BondPrimaryReselect::Failure, "failure".parse().unwrap());
assert!(BondPrimaryReselect::from_str("bogus").is_err());
}

#[test]
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::VlanSrcMac,
"vlan-src-mac".parse().unwrap()
);
assert!(BondXmitHashPolicy::from_str("bogus").is_err());
}

#[test]
fn test_bond_arp_all_targets_from_str() {
use std::str::FromStr;
assert_eq!(BondArpAllTargets::Any, "any".parse().unwrap());
assert_eq!(BondArpAllTargets::All, "all".parse().unwrap());
assert!(BondArpAllTargets::from_str("bogus").is_err());
}

#[test]
fn test_bond_fail_over_mac_from_str() {
use std::str::FromStr;
assert_eq!(BondFailOverMac::None, "none".parse().unwrap());
assert_eq!(BondFailOverMac::Active, "active".parse().unwrap());
assert_eq!(BondFailOverMac::Follow, "follow".parse().unwrap());
assert!(BondFailOverMac::from_str("bogus").is_err());
}

#[test]
fn test_bond_ad_select_from_str() {
use std::str::FromStr;
assert_eq!(BondAdSelect::Stable, "stable".parse().unwrap());
assert_eq!(BondAdSelect::Bandwidth, "bandwidth".parse().unwrap());
assert_eq!(BondAdSelect::Count, "count".parse().unwrap());
assert!(BondAdSelect::from_str("bogus").is_err());
}
Loading