netlink_packet_route/link/link_info/
mac_vlan.rs

1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::{
4    emit_i32, emit_u16, emit_u32, parse_i32, parse_mac, parse_u16, parse_u32,
5    DecodeError, DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer,
6    NlasIterator, Parseable,
7};
8
9const IFLA_MACVLAN_MODE: u16 = 1;
10const IFLA_MACVLAN_FLAGS: u16 = 2;
11const IFLA_MACVLAN_MACADDR_MODE: u16 = 3;
12const IFLA_MACVLAN_MACADDR: u16 = 4;
13const IFLA_MACVLAN_MACADDR_DATA: u16 = 5;
14const IFLA_MACVLAN_MACADDR_COUNT: u16 = 6;
15const IFLA_MACVLAN_BC_QUEUE_LEN: u16 = 7;
16const IFLA_MACVLAN_BC_QUEUE_LEN_USED: u16 = 8;
17const IFLA_MACVLAN_BC_CUTOFF: u16 = 9;
18
19#[derive(Debug, PartialEq, Eq, Clone)]
20#[non_exhaustive]
21pub enum InfoMacVlan {
22    Mode(MacVlanMode),
23    Flags(u16),
24    MacAddrMode(u32),
25    MacAddr([u8; 6]),
26    /// A list of InfoMacVlan::MacAddr
27    MacAddrData(Vec<InfoMacVlan>),
28    MacAddrCount(u32),
29    BcQueueLen(u32),
30    BcQueueLenUsed(u32),
31    BcCutoff(i32),
32    Other(DefaultNla),
33}
34
35impl Nla for InfoMacVlan {
36    fn value_len(&self) -> usize {
37        match self {
38            Self::Mode(_) => 4,
39            Self::Flags(_) => 2,
40            Self::MacAddrMode(_) => 4,
41            Self::MacAddr(_) => 6,
42            Self::MacAddrData(ref nlas) => nlas.as_slice().buffer_len(),
43            Self::MacAddrCount(_) => 4,
44            Self::BcQueueLen(_) => 4,
45            Self::BcQueueLenUsed(_) => 4,
46            Self::BcCutoff(_) => 4,
47            Self::Other(nla) => nla.value_len(),
48        }
49    }
50
51    fn emit_value(&self, buffer: &mut [u8]) {
52        match self {
53            Self::Mode(value) => emit_u32(buffer, (*value).into()).unwrap(),
54            Self::Flags(value) => emit_u16(buffer, *value).unwrap(),
55            Self::MacAddrMode(value) => emit_u32(buffer, *value).unwrap(),
56            Self::MacAddr(bytes) => buffer.copy_from_slice(bytes),
57            Self::MacAddrData(ref nlas) => nlas.as_slice().emit(buffer),
58            Self::MacAddrCount(value) => emit_u32(buffer, *value).unwrap(),
59            Self::BcQueueLen(value) => emit_u32(buffer, *value).unwrap(),
60            Self::BcQueueLenUsed(value) => emit_u32(buffer, *value).unwrap(),
61            Self::BcCutoff(value) => emit_i32(buffer, *value).unwrap(),
62            Self::Other(nla) => nla.emit_value(buffer),
63        }
64    }
65
66    fn kind(&self) -> u16 {
67        use self::InfoMacVlan::*;
68        match self {
69            Mode(_) => IFLA_MACVLAN_MODE,
70            Flags(_) => IFLA_MACVLAN_FLAGS,
71            MacAddrMode(_) => IFLA_MACVLAN_MACADDR_MODE,
72            MacAddr(_) => IFLA_MACVLAN_MACADDR,
73            MacAddrData(_) => IFLA_MACVLAN_MACADDR_DATA,
74            MacAddrCount(_) => IFLA_MACVLAN_MACADDR_COUNT,
75            BcQueueLen(_) => IFLA_MACVLAN_BC_QUEUE_LEN,
76            BcQueueLenUsed(_) => IFLA_MACVLAN_BC_QUEUE_LEN_USED,
77            BcCutoff(_) => IFLA_MACVLAN_BC_CUTOFF,
78            Other(nla) => nla.kind(),
79        }
80    }
81}
82
83impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacVlan {
84    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
85        use self::InfoMacVlan::*;
86        let payload = buf.value();
87        Ok(match buf.kind() {
88            IFLA_MACVLAN_MODE => Mode(
89                parse_u32(payload)
90                    .context("invalid IFLA_MACVLAN_MODE value")?
91                    .into(),
92            ),
93            IFLA_MACVLAN_FLAGS => Flags(
94                parse_u16(payload)
95                    .context("invalid IFLA_MACVLAN_FLAGS value")?,
96            ),
97            IFLA_MACVLAN_MACADDR_MODE => MacAddrMode(
98                parse_u32(payload)
99                    .context("invalid IFLA_MACVLAN_MACADDR_MODE value")?,
100            ),
101            IFLA_MACVLAN_MACADDR => MacAddr(
102                parse_mac(payload)
103                    .context("invalid IFLA_MACVLAN_MACADDR value")?,
104            ),
105            IFLA_MACVLAN_MACADDR_DATA => {
106                let mut mac_data = Vec::new();
107                let err = "failed to parse IFLA_MACVLAN_MACADDR_DATA";
108                for nla in NlasIterator::new(payload) {
109                    let nla = &nla.context(err)?;
110                    let parsed = InfoMacVlan::parse(nla).context(err)?;
111                    mac_data.push(parsed);
112                }
113                MacAddrData(mac_data)
114            }
115            IFLA_MACVLAN_MACADDR_COUNT => MacAddrCount(
116                parse_u32(payload)
117                    .context("invalid IFLA_MACVLAN_MACADDR_COUNT value")?,
118            ),
119            IFLA_MACVLAN_BC_QUEUE_LEN => BcQueueLen(
120                parse_u32(payload)
121                    .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN value")?,
122            ),
123            IFLA_MACVLAN_BC_QUEUE_LEN_USED => BcQueueLenUsed(
124                parse_u32(payload)
125                    .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN_USED value")?,
126            ),
127            IFLA_MACVLAN_BC_CUTOFF => BcCutoff(
128                parse_i32(payload)
129                    .context("invalid IFLA_MACVLAN_BC_CUTOFF value")?,
130            ),
131            kind => Other(DefaultNla::parse(buf).context(format!(
132                "unknown NLA type {kind} for IFLA_INFO_DATA(mac_vlan)"
133            ))?),
134        })
135    }
136}
137
138#[derive(Debug, PartialEq, Eq, Clone)]
139#[non_exhaustive]
140pub enum InfoMacVtap {
141    Mode(MacVtapMode),
142    Flags(u16),
143    MacAddrMode(u32),
144    MacAddr([u8; 6]),
145    MacAddrData(Vec<InfoMacVtap>),
146    MacAddrCount(u32),
147    BcQueueLen(u32),
148    BcQueueLenUsed(u32),
149    BcCutoff(i32),
150    Other(DefaultNla),
151}
152
153impl Nla for InfoMacVtap {
154    fn value_len(&self) -> usize {
155        use self::InfoMacVtap::*;
156        match self {
157            Mode(_) => 4,
158            Flags(_) => 2,
159            MacAddrMode(_) => 4,
160            MacAddr(_) => 6,
161            MacAddrData(ref nlas) => nlas.as_slice().buffer_len(),
162            MacAddrCount(_) => 4,
163            BcQueueLen(_) => 4,
164            BcQueueLenUsed(_) => 4,
165            BcCutoff(_) => 4,
166            Other(nla) => nla.value_len(),
167        }
168    }
169
170    fn emit_value(&self, buffer: &mut [u8]) {
171        use self::InfoMacVtap::*;
172        match self {
173            Mode(value) => emit_u32(buffer, (*value).into()).unwrap(),
174            Flags(value) => emit_u16(buffer, *value).unwrap(),
175            MacAddrMode(value) => emit_u32(buffer, *value).unwrap(),
176            MacAddr(bytes) => buffer.copy_from_slice(bytes),
177            MacAddrData(ref nlas) => nlas.as_slice().emit(buffer),
178            MacAddrCount(value) => emit_u32(buffer, *value).unwrap(),
179            BcQueueLen(value) => emit_u32(buffer, *value).unwrap(),
180            BcQueueLenUsed(value) => emit_u32(buffer, *value).unwrap(),
181            BcCutoff(value) => emit_i32(buffer, *value).unwrap(),
182            Other(nla) => nla.emit_value(buffer),
183        }
184    }
185
186    fn kind(&self) -> u16 {
187        use self::InfoMacVtap::*;
188        match self {
189            Mode(_) => IFLA_MACVLAN_MODE,
190            Flags(_) => IFLA_MACVLAN_FLAGS,
191            MacAddrMode(_) => IFLA_MACVLAN_MACADDR_MODE,
192            MacAddr(_) => IFLA_MACVLAN_MACADDR,
193            MacAddrData(_) => IFLA_MACVLAN_MACADDR_DATA,
194            MacAddrCount(_) => IFLA_MACVLAN_MACADDR_COUNT,
195            BcQueueLen(_) => IFLA_MACVLAN_BC_QUEUE_LEN,
196            BcQueueLenUsed(_) => IFLA_MACVLAN_BC_QUEUE_LEN_USED,
197            BcCutoff(_) => IFLA_MACVLAN_BC_CUTOFF,
198            Other(nla) => nla.kind(),
199        }
200    }
201}
202
203impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacVtap {
204    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
205        use self::InfoMacVtap::*;
206        let payload = buf.value();
207        Ok(match buf.kind() {
208            IFLA_MACVLAN_MODE => Mode(
209                parse_u32(payload)
210                    .context("invalid IFLA_MACVLAN_MODE value")?
211                    .into(),
212            ),
213            IFLA_MACVLAN_FLAGS => Flags(
214                parse_u16(payload)
215                    .context("invalid IFLA_MACVLAN_FLAGS value")?,
216            ),
217            IFLA_MACVLAN_MACADDR_MODE => MacAddrMode(
218                parse_u32(payload)
219                    .context("invalid IFLA_MACVLAN_MACADDR_MODE value")?,
220            ),
221            IFLA_MACVLAN_MACADDR => MacAddr(
222                parse_mac(payload)
223                    .context("invalid IFLA_MACVLAN_MACADDR value")?,
224            ),
225            IFLA_MACVLAN_MACADDR_DATA => {
226                let mut mac_data = Vec::new();
227                let err = "failed to parse IFLA_MACVLAN_MACADDR_DATA";
228                for nla in NlasIterator::new(payload) {
229                    let nla = &nla.context(err)?;
230                    let parsed = InfoMacVtap::parse(nla).context(err)?;
231                    mac_data.push(parsed);
232                }
233                MacAddrData(mac_data)
234            }
235            IFLA_MACVLAN_MACADDR_COUNT => MacAddrCount(
236                parse_u32(payload)
237                    .context("invalid IFLA_MACVLAN_MACADDR_COUNT value")?,
238            ),
239            IFLA_MACVLAN_BC_QUEUE_LEN => BcQueueLen(
240                parse_u32(payload)
241                    .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN value")?,
242            ),
243            IFLA_MACVLAN_BC_QUEUE_LEN_USED => BcQueueLenUsed(
244                parse_u32(payload)
245                    .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN_USED value")?,
246            ),
247            IFLA_MACVLAN_BC_CUTOFF => BcCutoff(
248                parse_i32(payload)
249                    .context("invalid IFLA_MACVLAN_BC_CUTOFF value")?,
250            ),
251            kind => Other(DefaultNla::parse(buf).context(format!(
252                "unknown NLA type {kind} for IFLA_INFO_DATA(mac_vtap)"
253            ))?),
254        })
255    }
256}
257
258const MACVLAN_MODE_PRIVATE: u32 = 1;
259const MACVLAN_MODE_VEPA: u32 = 2;
260const MACVLAN_MODE_BRIDGE: u32 = 4;
261const MACVLAN_MODE_PASSTHRU: u32 = 8;
262const MACVLAN_MODE_SOURCE: u32 = 16;
263
264#[derive(Debug, PartialEq, Eq, Clone, Copy)]
265#[non_exhaustive]
266pub enum MacVlanMode {
267    Private,
268    Vepa,
269    Bridge,
270    Passthrough,
271    Source,
272    Other(u32),
273}
274
275pub type MacVtapMode = MacVlanMode;
276
277impl From<u32> for MacVlanMode {
278    fn from(d: u32) -> Self {
279        match d {
280            MACVLAN_MODE_PRIVATE => Self::Private,
281            MACVLAN_MODE_VEPA => Self::Vepa,
282            MACVLAN_MODE_BRIDGE => Self::Bridge,
283            MACVLAN_MODE_PASSTHRU => Self::Passthrough,
284            MACVLAN_MODE_SOURCE => Self::Source,
285            _ => {
286                log::warn!("Unknown MAC VLAN mode {d}");
287                Self::Other(d)
288            }
289        }
290    }
291}
292
293impl From<MacVlanMode> for u32 {
294    fn from(v: MacVlanMode) -> u32 {
295        match v {
296            MacVlanMode::Private => MACVLAN_MODE_PRIVATE,
297            MacVlanMode::Vepa => MACVLAN_MODE_VEPA,
298            MacVlanMode::Bridge => MACVLAN_MODE_BRIDGE,
299            MacVlanMode::Passthrough => MACVLAN_MODE_PASSTHRU,
300            MacVlanMode::Source => MACVLAN_MODE_SOURCE,
301            MacVlanMode::Other(d) => d,
302        }
303    }
304}