diff --git a/src/link/link_info/bond.rs b/src/link/link_info/bond.rs index a7eab146..479e18a8 100644 --- a/src/link/link_info/bond.rs +++ b/src/link/link_info/bond.rs @@ -459,7 +459,7 @@ pub enum InfoBond { ArpAllTargets(BondArpAllTargets), Primary(u32), PrimaryReselect(u8), - FailOverMac(u8), + FailOverMac(BondFailOverMac), XmitHashPolicy(BondXmitHashPolicy), ResendIgmp(u32), NumPeerNotif(u8), @@ -528,7 +528,6 @@ impl Nla for InfoBond { Self::XmitHashPolicy(value) => buffer[0] = (*value).into(), Self::UseCarrier(value) | Self::PrimaryReselect(value) - | Self::FailOverMac(value) | Self::NumPeerNotif(value) | Self::AllPortsActive(value) | Self::AdLacpActive(value) @@ -536,6 +535,7 @@ impl Nla for InfoBond { | Self::AdSelect(value) | Self::TlbDynamicLb(value) | Self::MissedMax(value) => buffer[0] = *value, + Self::FailOverMac(value) => buffer[0] = (*value).into(), Self::AdActorSysPrio(value) | Self::AdUserPortKey(value) => { NativeEndian::write_u16(buffer, *value) } @@ -671,7 +671,8 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable> for InfoBond { ), IFLA_BOND_FAIL_OVER_MAC => Self::FailOverMac( parse_u8(payload) - .context("invalid IFLA_BOND_FAIL_OVER_MAC value")?, + .context("invalid IFLA_BOND_FAIL_OVER_MAC value")? + .into(), ), IFLA_BOND_XMIT_HASH_POLICY => Self::XmitHashPolicy( parse_u8(payload) @@ -766,3 +767,52 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable> for InfoBond { }) } } + +const BOND_FOM_NONE: u8 = 0; +const BOND_FOM_ACTIVE: u8 = 1; +const BOND_FOM_FOLLOW: u8 = 2; + +#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] +pub enum BondFailOverMac { + #[default] + None, + Active, + Follow, + Other(u8), +} + +impl From for u8 { + fn from(value: BondFailOverMac) -> Self { + match value { + BondFailOverMac::None => BOND_FOM_NONE, + BondFailOverMac::Active => BOND_FOM_ACTIVE, + BondFailOverMac::Follow => BOND_FOM_FOLLOW, + BondFailOverMac::Other(d) => d, + } + } +} + +impl From for BondFailOverMac { + fn from(value: u8) -> Self { + match value { + BOND_FOM_NONE => BondFailOverMac::None, + BOND_FOM_ACTIVE => BondFailOverMac::Active, + BOND_FOM_FOLLOW => BondFailOverMac::Follow, + d => BondFailOverMac::Other(d), + } + } +} + +impl std::fmt::Display for BondFailOverMac { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let kernel_name = match self { + BondFailOverMac::None => "none", + BondFailOverMac::Active => "active", + BondFailOverMac::Follow => "follow", + BondFailOverMac::Other(d) => { + return write!(f, "unknown-variant ({d})") + } + }; + f.write_str(kernel_name) + } +} diff --git a/src/link/link_info/mod.rs b/src/link/link_info/mod.rs index 24f262a5..2811d5ee 100644 --- a/src/link/link_info/mod.rs +++ b/src/link/link_info/mod.rs @@ -29,7 +29,7 @@ mod xfrm; mod xstats; pub use self::bond::{ - BondAdInfo, BondArpAllTargets, BondArpValidate, BondMode, + BondAdInfo, BondArpAllTargets, BondArpValidate, BondFailOverMac, BondMode, BondXmitHashPolicy, InfoBond, }; pub use self::bond_port::{BondPortState, InfoBondPort, MiiStatus}; diff --git a/src/link/mod.rs b/src/link/mod.rs index c3b4922c..c73fe784 100644 --- a/src/link/mod.rs +++ b/src/link/mod.rs @@ -39,17 +39,17 @@ pub use self::ext_mask::LinkExtentMask; pub use self::header::{LinkHeader, LinkMessageBuffer}; pub use self::link_flag::LinkFlags; pub use self::link_info::{ - BondAdInfo, BondArpAllTargets, BondArpValidate, BondMode, BondPortState, - BondXmitHashPolicy, BridgeId, BridgeIdBuffer, BridgePortMulticastRouter, - BridgePortState, BridgeQuerierState, GeneveDf, HsrProtocol, InfoBond, - InfoBondPort, InfoBridge, InfoBridgePort, InfoData, InfoGeneve, InfoGreTap, - InfoGreTap6, InfoGreTun, InfoGreTun6, InfoGtp, InfoHsr, InfoIpVlan, - InfoIpVtap, InfoIpoib, InfoKind, InfoMacSec, InfoMacVlan, InfoMacVtap, - InfoPortData, InfoPortKind, InfoSitTun, InfoTun, InfoVeth, InfoVlan, - InfoVrf, InfoVrfPort, InfoVti, InfoVxlan, InfoXfrm, IpVlanFlags, - IpVlanMode, IpVtapFlags, IpVtapMode, LinkInfo, LinkXstats, MacSecCipherId, - MacSecOffload, MacSecValidate, MacVlanMode, MacVtapMode, MiiStatus, - VlanQosMapping, + BondAdInfo, BondArpAllTargets, BondArpValidate, BondFailOverMac, BondMode, + BondPortState, BondXmitHashPolicy, BridgeId, BridgeIdBuffer, + BridgePortMulticastRouter, BridgePortState, BridgeQuerierState, GeneveDf, + HsrProtocol, InfoBond, InfoBondPort, InfoBridge, InfoBridgePort, InfoData, + InfoGeneve, InfoGreTap, InfoGreTap6, InfoGreTun, InfoGreTun6, InfoGtp, + InfoHsr, InfoIpVlan, InfoIpVtap, InfoIpoib, InfoKind, InfoMacSec, + InfoMacVlan, InfoMacVtap, InfoPortData, InfoPortKind, InfoSitTun, InfoTun, + InfoVeth, InfoVlan, InfoVrf, InfoVrfPort, InfoVti, InfoVxlan, InfoXfrm, + IpVlanFlags, IpVlanMode, IpVtapFlags, IpVtapMode, LinkInfo, LinkXstats, + MacSecCipherId, MacSecOffload, MacSecValidate, MacVlanMode, MacVtapMode, + MiiStatus, VlanQosMapping, }; pub use self::link_layer_type::LinkLayerType; pub use self::link_state::State; diff --git a/src/link/tests/bond.rs b/src/link/tests/bond.rs index d4dbdd79..7f39e677 100644 --- a/src/link/tests/bond.rs +++ b/src/link/tests/bond.rs @@ -4,9 +4,9 @@ use netlink_packet_utils::{Emitable, Parseable}; use crate::link::link_flag::LinkFlags; use crate::link::{ - BondArpAllTargets, BondArpValidate, BondMode, BondPortState, - BondXmitHashPolicy, InfoBond, InfoBondPort, InfoData, InfoKind, - InfoPortData, InfoPortKind, LinkAttribute, LinkHeader, LinkInfo, + BondArpAllTargets, BondArpValidate, BondFailOverMac, BondMode, + BondPortState, BondXmitHashPolicy, InfoBond, InfoBondPort, InfoData, + InfoKind, InfoPortData, InfoPortKind, LinkAttribute, LinkHeader, LinkInfo, LinkLayerType, LinkMessage, LinkMessageBuffer, Map, MiiStatus, State, }; use crate::{AddressFamily, RouteNetlinkMessage}; @@ -67,7 +67,7 @@ fn test_bond_link_info() { InfoBond::ArpValidate(BondArpValidate::None), InfoBond::ArpAllTargets(BondArpAllTargets::Any), InfoBond::PrimaryReselect(0), - InfoBond::FailOverMac(0), + InfoBond::FailOverMac(BondFailOverMac::None), InfoBond::XmitHashPolicy(BondXmitHashPolicy::Layer2), InfoBond::ResendIgmp(1), InfoBond::NumPeerNotif(1),