netlink_packet_route/rtnl/link/nlas/
bond_port.rs

1// SPDX-License-Identifier: MIT
2use 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}