netlink_packet_route/link/link_info/
mac_vlan.rs

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