netlink_packet_route/link/link_info/
bond_port.rs

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