netlink_packet_route/link/link_info/
bond_port.rs
1use anyhow::Context;
3use byteorder::{ByteOrder, NativeEndian};
4use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
5use netlink_packet_utils::parsers::{parse_i32, parse_u16, parse_u32, parse_u8};
6use netlink_packet_utils::traits::Parseable;
7use netlink_packet_utils::DecodeError;
8
9const IFLA_BOND_PORT_STATE_ACTIVE: u8 = 0;
10const IFLA_BOND_PORT_STATE_BACKUP: u8 = 1;
11
12const IFLA_BOND_PORT_MII_STATUS_UP: u8 = 0;
13const IFLA_BOND_PORT_MII_STATUS_GOING_DOWN: u8 = 1;
14const IFLA_BOND_PORT_MII_STATUS_DOWN: u8 = 2;
15const IFLA_BOND_PORT_MII_STATUS_GOING_BACK: u8 = 3;
16
17const IFLA_BOND_PORT_STATE: u16 = 1;
18const IFLA_BOND_PORT_MII_STATUS: u16 = 2;
19const IFLA_BOND_PORT_LINK_FAILURE_COUNT: u16 = 3;
20const IFLA_BOND_PORT_PERM_HWADDR: u16 = 4;
21const IFLA_BOND_PORT_QUEUE_ID: u16 = 5;
22const IFLA_BOND_PORT_PRIO: u16 = 9;
26
27#[derive(Debug, Clone, Copy, Eq, PartialEq)]
28#[non_exhaustive]
29pub enum BondPortState {
30 Active,
31 Backup,
32 Other(u8),
33}
34
35impl From<u8> for BondPortState {
36 fn from(value: u8) -> Self {
37 use self::BondPortState::*;
38 match value {
39 IFLA_BOND_PORT_STATE_ACTIVE => Active,
40 IFLA_BOND_PORT_STATE_BACKUP => Backup,
41 _ => Other(value),
42 }
43 }
44}
45
46impl From<BondPortState> for u8 {
47 fn from(value: BondPortState) -> Self {
48 use self::BondPortState::*;
49 match value {
50 Active => IFLA_BOND_PORT_STATE_ACTIVE,
51 Backup => IFLA_BOND_PORT_STATE_BACKUP,
52 Other(other) => other,
53 }
54 }
55}
56
57#[derive(Debug, Clone, Copy, Eq, PartialEq)]
58#[non_exhaustive]
59pub enum MiiStatus {
60 Up,
61 GoingDown,
62 Down,
63 GoingBack,
64 Other(u8),
65}
66
67impl From<u8> for MiiStatus {
68 fn from(value: u8) -> Self {
69 use self::MiiStatus::*;
70 match value {
71 IFLA_BOND_PORT_MII_STATUS_UP => Up,
72 IFLA_BOND_PORT_MII_STATUS_GOING_DOWN => GoingDown,
73 IFLA_BOND_PORT_MII_STATUS_DOWN => Down,
74 IFLA_BOND_PORT_MII_STATUS_GOING_BACK => GoingBack,
75 _ => Other(value),
76 }
77 }
78}
79
80impl From<MiiStatus> for u8 {
81 fn from(value: MiiStatus) -> Self {
82 use self::MiiStatus::*;
83 match value {
84 Up => IFLA_BOND_PORT_MII_STATUS_UP,
85 GoingDown => IFLA_BOND_PORT_MII_STATUS_GOING_DOWN,
86 Down => IFLA_BOND_PORT_MII_STATUS_DOWN,
87 GoingBack => IFLA_BOND_PORT_MII_STATUS_GOING_BACK,
88 Other(other) => other,
89 }
90 }
91}
92
93#[derive(Debug, PartialEq, Eq, Clone)]
94#[non_exhaustive]
95pub enum InfoBondPort {
96 LinkFailureCount(u32),
97 MiiStatus(MiiStatus),
98 PermHwaddr(Vec<u8>),
99 Prio(i32),
100 QueueId(u16),
101 BondPortState(BondPortState),
102 Other(DefaultNla),
103}
104
105impl Nla for InfoBondPort {
106 #[rustfmt::skip]
107 fn value_len(&self) -> usize {
108 use self::InfoBondPort::*;
109 match self {
110 QueueId(_)
111 => 2,
112 LinkFailureCount(_) |
113 Prio(_)
114 => 4,
115 PermHwaddr(ref bytes)
116 => bytes.len(),
117 MiiStatus(_) => 1,
118 BondPortState(_) => 1,
119 Other(nla)
120 => nla.value_len(),
121 }
122 }
123
124 #[rustfmt::skip]
125 fn emit_value(&self, buffer: &mut [u8]) {
126 use self::InfoBondPort::*;
127 match self {
128 QueueId(ref value)
129 => NativeEndian::write_u16(buffer, *value),
130 PermHwaddr(ref bytes)
131 => buffer.copy_from_slice(bytes.as_slice()),
132 Prio(ref value)
133 => NativeEndian::write_i32(buffer, *value),
134 LinkFailureCount(value)
135 => NativeEndian::write_u32(buffer, *value),
136 MiiStatus(state) => buffer[0] = (*state).into(),
137 BondPortState(state) => buffer[0] = (*state).into(),
138 Other(nla)
139 => nla.emit_value(buffer),
140 }
141 }
142
143 fn kind(&self) -> u16 {
144 use self::InfoBondPort::*;
145
146 match self {
147 LinkFailureCount(_) => IFLA_BOND_PORT_LINK_FAILURE_COUNT,
148 MiiStatus(_) => IFLA_BOND_PORT_MII_STATUS,
149 PermHwaddr(_) => IFLA_BOND_PORT_PERM_HWADDR,
150 Prio(_) => IFLA_BOND_PORT_PRIO,
151 QueueId(_) => IFLA_BOND_PORT_QUEUE_ID,
152 BondPortState(_) => IFLA_BOND_PORT_STATE,
153 Other(nla) => nla.kind(),
154 }
155 }
156}
157
158impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoBondPort {
159 type Error = DecodeError;
160 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
161 use self::InfoBondPort::*;
162 let payload = buf.value();
163 Ok(match buf.kind() {
164 IFLA_BOND_PORT_LINK_FAILURE_COUNT => LinkFailureCount(
165 parse_u32(payload).context("invalid IFLA_BOND_PORT_LINK_FAILURE_COUNT value")?,
166 ),
167 IFLA_BOND_PORT_MII_STATUS => MiiStatus(
168 parse_u8(payload).context("invalid IFLA_BOND_PORT_MII_STATUS value")?.into(),
169 ),
170 IFLA_BOND_PORT_PERM_HWADDR => PermHwaddr(payload.to_vec()),
171 IFLA_BOND_PORT_PRIO => {
172 Prio(parse_i32(payload).context("invalid IFLA_BOND_PORT_PRIO value")?)
173 }
174 IFLA_BOND_PORT_QUEUE_ID => {
175 QueueId(parse_u16(payload).context("invalid IFLA_BOND_PORT_QUEUE_ID value")?)
176 }
177 IFLA_BOND_PORT_STATE => BondPortState(
178 parse_u8(payload).context("invalid IFLA_BOND_PORT_STATE value")?.into(),
179 ),
180 kind => Other(DefaultNla::parse(buf).context(format!("unknown NLA type {kind}"))?),
181 })
182 }
183}