netlink_packet_route/link/link_info/
mac_vlan.rs
1use 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 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}