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(MacVlanFlags),
24    MacAddrMode(MacVlanMacAddressMode),
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.bits()).unwrap(),
55            Self::MacAddrMode(value) => {
56                emit_u32(buffer, (*value).into()).unwrap()
57            }
58            Self::MacAddr(bytes) => buffer.copy_from_slice(bytes),
59            Self::MacAddrData(ref nlas) => nlas.as_slice().emit(buffer),
60            Self::MacAddrCount(value) => emit_u32(buffer, *value).unwrap(),
61            Self::BcQueueLen(value) => emit_u32(buffer, *value).unwrap(),
62            Self::BcQueueLenUsed(value) => emit_u32(buffer, *value).unwrap(),
63            Self::BcCutoff(value) => emit_i32(buffer, *value).unwrap(),
64            Self::Other(nla) => nla.emit_value(buffer),
65        }
66    }
67
68    fn kind(&self) -> u16 {
69        use self::InfoMacVlan::*;
70        match self {
71            Mode(_) => IFLA_MACVLAN_MODE,
72            Flags(_) => IFLA_MACVLAN_FLAGS,
73            MacAddrMode(_) => IFLA_MACVLAN_MACADDR_MODE,
74            MacAddr(_) => IFLA_MACVLAN_MACADDR,
75            MacAddrData(_) => IFLA_MACVLAN_MACADDR_DATA,
76            MacAddrCount(_) => IFLA_MACVLAN_MACADDR_COUNT,
77            BcQueueLen(_) => IFLA_MACVLAN_BC_QUEUE_LEN,
78            BcQueueLenUsed(_) => IFLA_MACVLAN_BC_QUEUE_LEN_USED,
79            BcCutoff(_) => IFLA_MACVLAN_BC_CUTOFF,
80            Other(nla) => nla.kind(),
81        }
82    }
83}
84
85impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacVlan {
86    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
87        use self::InfoMacVlan::*;
88        let payload = buf.value();
89        Ok(match buf.kind() {
90            IFLA_MACVLAN_MODE => Mode(
91                parse_u32(payload)
92                    .context("invalid IFLA_MACVLAN_MODE value")?
93                    .into(),
94            ),
95            IFLA_MACVLAN_FLAGS => Flags(MacVlanFlags::from_bits_retain(
96                parse_u16(payload)
97                    .context("invalid IFLA_MACVLAN_FLAGS value")?,
98            )),
99            IFLA_MACVLAN_MACADDR_MODE => MacAddrMode(
100                parse_u32(payload)
101                    .context("invalid IFLA_MACVLAN_MACADDR_MODE value")?
102                    .into(),
103            ),
104            IFLA_MACVLAN_MACADDR => MacAddr(
105                parse_mac(payload)
106                    .context("invalid IFLA_MACVLAN_MACADDR value")?,
107            ),
108            IFLA_MACVLAN_MACADDR_DATA => {
109                let mut mac_data = Vec::new();
110                let err = "failed to parse IFLA_MACVLAN_MACADDR_DATA";
111                for nla in NlasIterator::new(payload) {
112                    let nla = &nla.context(err)?;
113                    let parsed = InfoMacVlan::parse(nla).context(err)?;
114                    mac_data.push(parsed);
115                }
116                MacAddrData(mac_data)
117            }
118            IFLA_MACVLAN_MACADDR_COUNT => MacAddrCount(
119                parse_u32(payload)
120                    .context("invalid IFLA_MACVLAN_MACADDR_COUNT value")?,
121            ),
122            IFLA_MACVLAN_BC_QUEUE_LEN => BcQueueLen(
123                parse_u32(payload)
124                    .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN value")?,
125            ),
126            IFLA_MACVLAN_BC_QUEUE_LEN_USED => BcQueueLenUsed(
127                parse_u32(payload)
128                    .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN_USED value")?,
129            ),
130            IFLA_MACVLAN_BC_CUTOFF => BcCutoff(
131                parse_i32(payload)
132                    .context("invalid IFLA_MACVLAN_BC_CUTOFF value")?,
133            ),
134            kind => Other(DefaultNla::parse(buf).context(format!(
135                "unknown NLA type {kind} for IFLA_INFO_DATA(mac_vlan)"
136            ))?),
137        })
138    }
139}
140
141#[derive(Debug, PartialEq, Eq, Clone)]
142#[non_exhaustive]
143pub enum InfoMacVtap {
144    Mode(MacVtapMode),
145    Flags(MacVtapFlags),
146    MacAddrMode(MacVtapMacAddressMode),
147    MacAddr([u8; 6]),
148    MacAddrData(Vec<InfoMacVtap>),
149    MacAddrCount(u32),
150    BcQueueLen(u32),
151    BcQueueLenUsed(u32),
152    BcCutoff(i32),
153    Other(DefaultNla),
154}
155
156impl Nla for InfoMacVtap {
157    fn value_len(&self) -> usize {
158        use self::InfoMacVtap::*;
159        match self {
160            Mode(_) => 4,
161            Flags(_) => 2,
162            MacAddrMode(_) => 4,
163            MacAddr(_) => 6,
164            MacAddrData(ref nlas) => nlas.as_slice().buffer_len(),
165            MacAddrCount(_) => 4,
166            BcQueueLen(_) => 4,
167            BcQueueLenUsed(_) => 4,
168            BcCutoff(_) => 4,
169            Other(nla) => nla.value_len(),
170        }
171    }
172
173    fn emit_value(&self, buffer: &mut [u8]) {
174        use self::InfoMacVtap::*;
175        match self {
176            Mode(value) => emit_u32(buffer, (*value).into()).unwrap(),
177            Flags(value) => emit_u16(buffer, value.bits()).unwrap(),
178            MacAddrMode(value) => emit_u32(buffer, (*value).into()).unwrap(),
179            MacAddr(bytes) => buffer.copy_from_slice(bytes),
180            MacAddrData(ref nlas) => nlas.as_slice().emit(buffer),
181            MacAddrCount(value) => emit_u32(buffer, *value).unwrap(),
182            BcQueueLen(value) => emit_u32(buffer, *value).unwrap(),
183            BcQueueLenUsed(value) => emit_u32(buffer, *value).unwrap(),
184            BcCutoff(value) => emit_i32(buffer, *value).unwrap(),
185            Other(nla) => nla.emit_value(buffer),
186        }
187    }
188
189    fn kind(&self) -> u16 {
190        use self::InfoMacVtap::*;
191        match self {
192            Mode(_) => IFLA_MACVLAN_MODE,
193            Flags(_) => IFLA_MACVLAN_FLAGS,
194            MacAddrMode(_) => IFLA_MACVLAN_MACADDR_MODE,
195            MacAddr(_) => IFLA_MACVLAN_MACADDR,
196            MacAddrData(_) => IFLA_MACVLAN_MACADDR_DATA,
197            MacAddrCount(_) => IFLA_MACVLAN_MACADDR_COUNT,
198            BcQueueLen(_) => IFLA_MACVLAN_BC_QUEUE_LEN,
199            BcQueueLenUsed(_) => IFLA_MACVLAN_BC_QUEUE_LEN_USED,
200            BcCutoff(_) => IFLA_MACVLAN_BC_CUTOFF,
201            Other(nla) => nla.kind(),
202        }
203    }
204}
205
206impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacVtap {
207    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
208        use self::InfoMacVtap::*;
209        let payload = buf.value();
210        Ok(match buf.kind() {
211            IFLA_MACVLAN_MODE => Mode(
212                parse_u32(payload)
213                    .context("invalid IFLA_MACVLAN_MODE value")?
214                    .into(),
215            ),
216            IFLA_MACVLAN_FLAGS => Flags(MacVtapFlags::from_bits_retain(
217                parse_u16(payload)
218                    .context("invalid IFLA_MACVLAN_FLAGS value")?,
219            )),
220            IFLA_MACVLAN_MACADDR_MODE => MacAddrMode(
221                parse_u32(payload)
222                    .context("invalid IFLA_MACVLAN_MACADDR_MODE value")?
223                    .into(),
224            ),
225            IFLA_MACVLAN_MACADDR => MacAddr(
226                parse_mac(payload)
227                    .context("invalid IFLA_MACVLAN_MACADDR value")?,
228            ),
229            IFLA_MACVLAN_MACADDR_DATA => {
230                let mut mac_data = Vec::new();
231                let err = "failed to parse IFLA_MACVLAN_MACADDR_DATA";
232                for nla in NlasIterator::new(payload) {
233                    let nla = &nla.context(err)?;
234                    let parsed = InfoMacVtap::parse(nla).context(err)?;
235                    mac_data.push(parsed);
236                }
237                MacAddrData(mac_data)
238            }
239            IFLA_MACVLAN_MACADDR_COUNT => MacAddrCount(
240                parse_u32(payload)
241                    .context("invalid IFLA_MACVLAN_MACADDR_COUNT value")?,
242            ),
243            IFLA_MACVLAN_BC_QUEUE_LEN => BcQueueLen(
244                parse_u32(payload)
245                    .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN value")?,
246            ),
247            IFLA_MACVLAN_BC_QUEUE_LEN_USED => BcQueueLenUsed(
248                parse_u32(payload)
249                    .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN_USED value")?,
250            ),
251            IFLA_MACVLAN_BC_CUTOFF => BcCutoff(
252                parse_i32(payload)
253                    .context("invalid IFLA_MACVLAN_BC_CUTOFF value")?,
254            ),
255            kind => Other(DefaultNla::parse(buf).context(format!(
256                "unknown NLA type {kind} for IFLA_INFO_DATA(mac_vtap)"
257            ))?),
258        })
259    }
260}
261
262const MACVLAN_MODE_PRIVATE: u32 = 1;
263const MACVLAN_MODE_VEPA: u32 = 2;
264const MACVLAN_MODE_BRIDGE: u32 = 4;
265const MACVLAN_MODE_PASSTHRU: u32 = 8;
266const MACVLAN_MODE_SOURCE: u32 = 16;
267
268#[derive(Debug, PartialEq, Eq, Clone, Copy)]
269#[non_exhaustive]
270pub enum MacVlanMode {
271    Private,
272    Vepa,
273    Bridge,
274    Passthrough,
275    Source,
276    Other(u32),
277}
278
279pub type MacVtapMode = MacVlanMode;
280pub type MacVtapFlags = MacVlanFlags;
281
282impl From<u32> for MacVlanMode {
283    fn from(d: u32) -> Self {
284        match d {
285            MACVLAN_MODE_PRIVATE => Self::Private,
286            MACVLAN_MODE_VEPA => Self::Vepa,
287            MACVLAN_MODE_BRIDGE => Self::Bridge,
288            MACVLAN_MODE_PASSTHRU => Self::Passthrough,
289            MACVLAN_MODE_SOURCE => Self::Source,
290            _ => {
291                log::warn!("Unknown MAC VLAN mode {d}");
292                Self::Other(d)
293            }
294        }
295    }
296}
297
298impl From<MacVlanMode> for u32 {
299    fn from(v: MacVlanMode) -> u32 {
300        match v {
301            MacVlanMode::Private => MACVLAN_MODE_PRIVATE,
302            MacVlanMode::Vepa => MACVLAN_MODE_VEPA,
303            MacVlanMode::Bridge => MACVLAN_MODE_BRIDGE,
304            MacVlanMode::Passthrough => MACVLAN_MODE_PASSTHRU,
305            MacVlanMode::Source => MACVLAN_MODE_SOURCE,
306            MacVlanMode::Other(d) => d,
307        }
308    }
309}
310
311const MACVLAN_FLAG_NOPROMISC: u16 = 1;
312const MACVLAN_FLAG_NODST: u16 = 2;
313
314bitflags! {
315    #[non_exhaustive]
316    #[derive(Debug, Clone, Copy, Eq, PartialEq)]
317    pub struct MacVlanFlags: u16 {
318        const NoPromisc = MACVLAN_FLAG_NOPROMISC;
319        const NoDst = MACVLAN_FLAG_NODST;
320        const _ = !0;
321    }
322}
323
324const MACVLAN_MACADDR_ADD: u32 = 0;
325const MACVLAN_MACADDR_DEL: u32 = 1;
326const MACVLAN_MACADDR_FLUSH: u32 = 2;
327const MACVLAN_MACADDR_SET: u32 = 3;
328
329#[derive(Debug, PartialEq, Eq, Clone, Copy)]
330#[non_exhaustive]
331pub enum MacVlanMacAddressMode {
332    Add,
333    Del,
334    Flush,
335    Set,
336    Other(u32),
337}
338
339pub type MacVtapMacAddressMode = MacVlanMacAddressMode;
340
341impl From<u32> for MacVlanMacAddressMode {
342    fn from(d: u32) -> Self {
343        match d {
344            MACVLAN_MACADDR_ADD => Self::Add,
345            MACVLAN_MACADDR_DEL => Self::Del,
346            MACVLAN_MACADDR_FLUSH => Self::Flush,
347            MACVLAN_MACADDR_SET => Self::Set,
348            _ => Self::Other(d),
349        }
350    }
351}
352
353impl From<MacVlanMacAddressMode> for u32 {
354    fn from(v: MacVlanMacAddressMode) -> u32 {
355        match v {
356            MacVlanMacAddressMode::Add => MACVLAN_MACADDR_ADD,
357            MacVlanMacAddressMode::Del => MACVLAN_MACADDR_DEL,
358            MacVlanMacAddressMode::Flush => MACVLAN_MACADDR_FLUSH,
359            MacVlanMacAddressMode::Set => MACVLAN_MACADDR_SET,
360            MacVlanMacAddressMode::Other(d) => d,
361        }
362    }
363}