netlink_packet_route/link/link_info/
bond_port.rs

1// SPDX-License-Identifier: MIT
2use 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;
22// const IFLA_BOND_PORT_AD_AGGREGATOR_ID: u16 = 6;
23// const IFLA_BOND_PORT_AD_ACTOR_OPER_PORT_STATE: u16 = 7;
24// const IFLA_BOND_PORT_AD_PARTNER_OPER_PORT_STATE: u16 = 8;
25const 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}