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