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 <[email protected]>
  • Loading branch information
Gilnaa committed May 26, 2024
1 parent 3e16f9c commit 1f51fc8
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 11 deletions.
80 changes: 77 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,65 @@ impl std::fmt::Display for BondMode {
}
}

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

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

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

impl std::fmt::Display for ArpValidate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let kernel_name = match self {
ArpValidate::None => "none",
ArpValidate::Active => "active",
ArpValidate::Backup => "backup",
ArpValidate::All => "all",
ArpValidate::Filter => "filter",
ArpValidate::FilterActive => "filter_active",
ArpValidate::FilterBackup => "filter_backup",
ArpValidate::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 +347,7 @@ pub enum InfoBond {
UseCarrier(u8),
ArpInterval(u32),
ArpIpTarget(Vec<Ipv4Addr>),
ArpValidate(u32),
ArpValidate(ArpValidate),
ArpAllTargets(u32),
Primary(u32),
PrimaryReselect(u8),
Expand Down Expand Up @@ -360,12 +431,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 +543,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 @@ -27,7 +27,7 @@ mod vxlan;
mod xfrm;
mod xstats;

pub use self::bond::{BondAdInfo, BondMode, InfoBond};
pub use self::bond::{ArpValidate, BondAdInfo, BondMode, InfoBond};
pub use self::bond_port::{BondPortState, InfoBondPort, MiiStatus};
pub use self::bridge::{
BridgeId, BridgeIdBuffer, BridgeQuerierState, InfoBridge,
Expand Down
2 changes: 1 addition & 1 deletion src/link/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ 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,
ArpValidate, BondAdInfo, BondMode, BondPortState, BridgeId, BridgeIdBuffer,
BridgePortMulticastRouter, BridgePortState, BridgeQuerierState,
HsrProtocol, InfoBond, InfoBondPort, InfoBridge, InfoBridgePort, InfoData,
InfoGreTap, InfoGreTap6, InfoGreTun, InfoGreTun6, InfoGtp, InfoHsr,
Expand Down
94 changes: 88 additions & 6 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,
ArpValidate, 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 @@ -56,14 +58,14 @@ fn test_bond_link_info() {
attributes: vec![LinkAttribute::LinkInfo(vec![
LinkInfo::Kind(InfoKind::Bond),
LinkInfo::Data(InfoData::Bond(vec![
InfoBond::Mode(BondMode::BalanceRr),
InfoBond::Mode(BondMode::default()),
InfoBond::MiiMon(0),
InfoBond::UpDelay(0),
InfoBond::DownDelay(0),
InfoBond::PeerNotifDelay(0),
InfoBond::UseCarrier(1),
InfoBond::ArpInterval(0),
InfoBond::ArpValidate(0),
InfoBond::ArpValidate(ArpValidate::default()),
InfoBond::ArpAllTargets(0),
InfoBond::PrimaryReselect(0),
InfoBond::FailOverMac(0),
Expand Down Expand Up @@ -149,3 +151,83 @@ fn test_bond_port_link_info() {

assert_eq!(buf, raw);
}

#[test]
fn test_bond_arp_validate() {
let raw: Vec<u8> = vec![
0xfc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xa5, 0xb9, 0x52, 0x66,
0x37, 0xa7, 0x3d, 0x00, 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 mut packet = NetlinkMessage::new(
NetlinkHeader::default(),
NetlinkPayload::from(RouteNetlinkMessage::NewLink(expected)),
);
packet.header.sequence_number = 1716697509;
packet.header.port_number = 4040503;
packet.finalize();
let mut buf = vec![0u8; packet.buffer_len()];
packet.serialize(&mut buf);

assert_eq!(raw, buf);
}

0 comments on commit 1f51fc8

Please sign in to comment.