Skip to content

Commit

Permalink
Convert InfoBond::ArpValidate into an enum.
Browse files Browse the repository at this point in the history
Closes #80

Signed-off-by: Gilad Naaman <gilad@naaman.io>
  • Loading branch information
Gilnaa authored and cathay4t committed Sep 4, 2024
1 parent 538e13b commit 5246712
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 19 deletions.
82 changes: 79 additions & 3 deletions src/link/link_info/bond.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ const BOND_MODE_8023AD: u8 = 4;
const BOND_MODE_TLB: u8 = 5;
const BOND_MODE_ALB: u8 = 6;

const BOND_STATE_ACTIVE: u8 = 0;
const BOND_STATE_BACKUP: u8 = 1;

const BOND_ARP_VALIDATE_NONE: u32 = 0;
const BOND_ARP_VALIDATE_ACTIVE: u32 = 1 << BOND_STATE_ACTIVE as u32;
const BOND_ARP_VALIDATE_BACKUP: u32 = 1 << BOND_STATE_BACKUP as u32;
const BOND_ARP_VALIDATE_ALL: u32 =
BOND_ARP_VALIDATE_ACTIVE | BOND_ARP_VALIDATE_BACKUP;
const BOND_ARP_FILTER: u32 = BOND_ARP_VALIDATE_ALL + 1;
const BOND_ARP_FILTER_ACTIVE: u32 = BOND_ARP_FILTER | BOND_ARP_VALIDATE_ACTIVE;
const BOND_ARP_FILTER_BACKUP: u32 = BOND_ARP_FILTER | BOND_ARP_VALIDATE_BACKUP;

#[derive(Debug, Clone, Eq, PartialEq)]
#[non_exhaustive]
pub enum BondAdInfo {
Expand Down Expand Up @@ -199,6 +211,67 @@ impl std::fmt::Display for BondMode {
}
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
pub enum BondArpValidate {
#[default]
None,
Active,
Backup,
All,
Filter,
FilterActive,
FilterBackup,
Other(u32),
}

impl From<BondArpValidate> for u32 {
fn from(value: BondArpValidate) -> Self {
match value {
BondArpValidate::None => BOND_ARP_VALIDATE_NONE,
BondArpValidate::Active => BOND_ARP_VALIDATE_ACTIVE,
BondArpValidate::Backup => BOND_ARP_VALIDATE_BACKUP,
BondArpValidate::All => BOND_ARP_VALIDATE_ALL,
BondArpValidate::Filter => BOND_ARP_FILTER,
BondArpValidate::FilterActive => BOND_ARP_FILTER_ACTIVE,
BondArpValidate::FilterBackup => BOND_ARP_FILTER_BACKUP,
BondArpValidate::Other(d) => d,
}
}
}

impl From<u32> for BondArpValidate {
fn from(value: u32) -> Self {
match value {
BOND_ARP_VALIDATE_NONE => BondArpValidate::None,
BOND_ARP_VALIDATE_ACTIVE => BondArpValidate::Active,
BOND_ARP_VALIDATE_BACKUP => BondArpValidate::Backup,
BOND_ARP_VALIDATE_ALL => BondArpValidate::All,
BOND_ARP_FILTER => BondArpValidate::Filter,
BOND_ARP_FILTER_ACTIVE => BondArpValidate::FilterActive,
BOND_ARP_FILTER_BACKUP => BondArpValidate::FilterBackup,
d => BondArpValidate::Other(d),
}
}
}

impl std::fmt::Display for BondArpValidate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let kernel_name = match self {
BondArpValidate::None => "none",
BondArpValidate::Active => "active",
BondArpValidate::Backup => "backup",
BondArpValidate::All => "all",
BondArpValidate::Filter => "filter",
BondArpValidate::FilterActive => "filter_active",
BondArpValidate::FilterBackup => "filter_backup",
BondArpValidate::Other(d) => {
return write!(f, "unknown-variant ({d})")
}
};
f.write_str(kernel_name)
}
}

// 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 @@ -276,7 +349,7 @@ pub enum InfoBond {
UseCarrier(u8),
ArpInterval(u32),
ArpIpTarget(Vec<Ipv4Addr>),
ArpValidate(u32),
ArpValidate(BondArpValidate),
ArpAllTargets(u32),
Primary(u32),
PrimaryReselect(u8),
Expand Down Expand Up @@ -360,12 +433,14 @@ impl Nla for InfoBond {
Self::AdActorSysPrio(value) | Self::AdUserPortKey(value) => {
NativeEndian::write_u16(buffer, *value)
}
Self::ArpValidate(value) => {
NativeEndian::write_u32(buffer, (*value).into())
}
Self::ActivePort(value)
| Self::MiiMon(value)
| Self::UpDelay(value)
| Self::DownDelay(value)
| Self::ArpInterval(value)
| Self::ArpValidate(value)
| Self::ArpAllTargets(value)
| Self::Primary(value)
| Self::ResendIgmp(value)
Expand Down Expand Up @@ -470,7 +545,8 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoBond {
}
IFLA_BOND_ARP_VALIDATE => Self::ArpValidate(
parse_u32(payload)
.context("invalid IFLA_BOND_ARP_VALIDATE value")?,
.context("invalid IFLA_BOND_ARP_VALIDATE value")?
.into(),
),
IFLA_BOND_ARP_ALL_TARGETS => Self::ArpAllTargets(
parse_u32(payload)
Expand Down
2 changes: 1 addition & 1 deletion src/link/link_info/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ mod vxlan;
mod xfrm;
mod xstats;

pub use self::bond::{BondAdInfo, BondMode, InfoBond};
pub use self::bond::{BondAdInfo, BondArpValidate, BondMode, InfoBond};
pub use self::bond_port::{BondPortState, InfoBondPort, MiiStatus};
pub use self::bridge::{
BridgeId, BridgeIdBuffer, BridgeQuerierState, InfoBridge,
Expand Down
20 changes: 10 additions & 10 deletions src/link/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,16 @@ pub use self::ext_mask::LinkExtentMask;
pub use self::header::{LinkHeader, LinkMessageBuffer};
pub use self::link_flag::LinkFlags;
pub use self::link_info::{
BondAdInfo, BondMode, BondPortState, 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,
IpVlanMode, IpVtapMode, LinkInfo, LinkXstats, MacSecCipherId,
MacSecOffload, MacSecValidate, MacVlanMode, MacVtapMode, MiiStatus,
VlanQosMapping,
BondAdInfo, BondArpValidate, BondMode, BondPortState, 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, IpVlanMode, IpVtapMode,
LinkInfo, LinkXstats, MacSecCipherId, MacSecOffload, MacSecValidate,
MacVlanMode, MacVtapMode, MiiStatus, VlanQosMapping,
};
pub use self::link_layer_type::LinkLayerType;
pub use self::link_state::State;
Expand Down
86 changes: 81 additions & 5 deletions src/link/tests/bond.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
// SPDX-License-Identifier: MIT

use netlink_packet_core::{NetlinkHeader, NetlinkMessage, NetlinkPayload};
use netlink_packet_utils::{Emitable, Parseable};

use crate::link::link_flag::LinkFlags;
use crate::link::{
BondMode, BondPortState, InfoBond, InfoBondPort, InfoData, InfoKind,
InfoPortData, InfoPortKind, LinkAttribute, LinkHeader, LinkInfo,
LinkLayerType, LinkMessage, LinkMessageBuffer, MiiStatus,
BondArpValidate, BondMode, BondPortState, InfoBond, InfoBondPort, InfoData,
InfoKind, InfoPortData, InfoPortKind, LinkAttribute, LinkHeader, LinkInfo,
LinkLayerType, LinkMessage, LinkMessageBuffer, LinkXdp, Map, MiiStatus,
State, Stats, Stats64,
};
use crate::AddressFamily;
use crate::{AddressFamily, RouteNetlinkMessage};

#[test]
fn test_bond_link_info() {
Expand Down Expand Up @@ -63,7 +65,7 @@ fn test_bond_link_info() {
InfoBond::PeerNotifDelay(0),
InfoBond::UseCarrier(1),
InfoBond::ArpInterval(0),
InfoBond::ArpValidate(0),
InfoBond::ArpValidate(BondArpValidate::None),
InfoBond::ArpAllTargets(0),
InfoBond::PrimaryReselect(0),
InfoBond::FailOverMac(0),
Expand Down Expand Up @@ -149,3 +151,77 @@ fn test_bond_port_link_info() {

assert_eq!(buf, raw);
}

#[test]
fn test_bond_arp_validate() {
let raw: Vec<u8> = vec![
0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x03, 0x00, 0x62, 0x6f, 0x6e, 0x64,
0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0xe8, 0x03, 0x00, 0x00,
0x05, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0xdc, 0x05, 0x00, 0x00,
0x08, 0x00, 0x32, 0x00, 0x44, 0x00, 0x00, 0x00, 0x08, 0x00, 0x33, 0x00,
0xff, 0xff, 0x00, 0x00, 0x08, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1f, 0x00,
0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0xff, 0xff, 0x00, 0x00,
0x08, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x20, 0x00,
0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
0x09, 0x00, 0x06, 0x00, 0x6e, 0x6f, 0x6f, 0x70, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x2f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00,
0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x0e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00,
0x92, 0xb3, 0xba, 0x20, 0xd7, 0xa0, 0x00, 0x00, 0x0a, 0x00, 0x02, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
];
let expected = LinkMessage {
header: LinkHeader {
interface_family: AddressFamily::Unspec,
index: 5,
link_layer_type: LinkLayerType::Ether,
flags: LinkFlags::Broadcast
| LinkFlags::Controller
| LinkFlags::Multicast,
change_mask: LinkFlags::empty(),
},
attributes: vec![
LinkAttribute::IfName("bond0".into()),
LinkAttribute::TxQueueLen(1000),
LinkAttribute::OperState(State::Down),
LinkAttribute::Mode(0),
LinkAttribute::Mtu(1500),
LinkAttribute::MinMtu(68),
LinkAttribute::MaxMtu(65535),
LinkAttribute::Group(0),
LinkAttribute::Promiscuity(0),
LinkAttribute::NumTxQueues(16),
LinkAttribute::GsoMaxSegs(65535),
LinkAttribute::GsoMaxSize(65536),
LinkAttribute::NumRxQueues(16),
LinkAttribute::Carrier(0),
LinkAttribute::Qdisc("noop".into()),
LinkAttribute::CarrierChanges(1),
LinkAttribute::CarrierUpCount(0),
LinkAttribute::CarrierDownCount(1),
LinkAttribute::ProtoDown(0),
LinkAttribute::Map(Map {
memory_start: 0,
memory_end: 0,
base_address: 0,
irq: 0,
dma: 0,
port: 0,
}),
LinkAttribute::Address(vec![0x92, 0xb3, 0xba, 0x20, 0xd7, 0xa0]),
LinkAttribute::Broadcast(vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff]),
],
};

let packet = RouteNetlinkMessage::NewLink(expected);
let mut buf = vec![0u8; packet.buffer_len()];
packet.emit(&mut buf);

assert_eq!(raw, buf);
}

0 comments on commit 5246712

Please sign in to comment.