1use std::os::unix::io::RawFd;
4
5use netlink_packet_core::{
6 emit_i32, emit_u32, parse_i32, parse_string, parse_u32, parse_u8,
7 DecodeError, DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer,
8 NlasIterator, Parseable, ParseableParametrized, NLA_F_NESTED,
9};
10
11#[cfg(any(
12 target_os = "linux",
13 target_os = "fuchsia",
14 target_os = "android"
15))]
16use super::af_spec::VecAfSpecBridge;
17#[cfg(any(
18 target_os = "linux",
19 target_os = "fuchsia",
20 target_os = "android"
21))]
22use super::proto_info::VecLinkProtoInfoBridge;
23use super::{
24 af_spec::VecAfSpecUnspec,
25 buffer_tool::expand_buffer_if_small,
26 ext_mask::VecLinkExtentMask,
27 link_info::VecLinkInfo,
28 proto_info::VecLinkProtoInfoInet6,
29 sriov::{VecLinkVfInfo, VecLinkVfPort},
30 stats::LINK_STATS_LEN,
31 stats64::LINK_STATS64_LEN,
32 xdp::VecLinkXdp,
33 AfSpecBridge, AfSpecUnspec, LinkEvent, LinkExtentMask, LinkInfo, LinkMode,
34 LinkPhysId, LinkProtoInfoBridge, LinkProtoInfoInet6,
35 LinkProtocolDownReason, LinkVfInfo, LinkVfPort, LinkWirelessEvent, LinkXdp,
36 Map, MapBuffer, Prop, State, Stats, Stats64, Stats64Buffer, StatsBuffer,
37};
38use crate::AddressFamily;
39
40const IFLA_ADDRESS: u16 = 1;
41const IFLA_BROADCAST: u16 = 2;
42const IFLA_IFNAME: u16 = 3;
43const IFLA_MTU: u16 = 4;
44const IFLA_LINK: u16 = 5;
45const IFLA_QDISC: u16 = 6;
46const IFLA_STATS: u16 = 7;
47const IFLA_MASTER: u16 = 10;
52const IFLA_WIRELESS: u16 = 11;
53const IFLA_PROTINFO: u16 = 12;
54const IFLA_TXQLEN: u16 = 13;
55const IFLA_MAP: u16 = 14;
56const IFLA_OPERSTATE: u16 = 16;
59const IFLA_LINKMODE: u16 = 17;
60const IFLA_LINKINFO: u16 = 18;
61const IFLA_NET_NS_PID: u16 = 19;
62const IFLA_IFALIAS: u16 = 20;
63const IFLA_NUM_VF: u16 = 21;
64const IFLA_VFINFO_LIST: u16 = 22;
65const IFLA_STATS64: u16 = 23;
66const IFLA_VF_PORTS: u16 = 24;
67const IFLA_PORT_SELF: u16 = 25;
68const IFLA_AF_SPEC: u16 = 26;
69const IFLA_GROUP: u16 = 27;
70const IFLA_NET_NS_FD: u16 = 28;
71const IFLA_EXT_MASK: u16 = 29;
72const IFLA_PROMISCUITY: u16 = 30;
73const IFLA_NUM_TX_QUEUES: u16 = 31;
74const IFLA_NUM_RX_QUEUES: u16 = 32;
75const IFLA_CARRIER: u16 = 33;
76const IFLA_PHYS_PORT_ID: u16 = 34;
77const IFLA_CARRIER_CHANGES: u16 = 35;
78const IFLA_PHYS_SWITCH_ID: u16 = 36;
79const IFLA_LINK_NETNSID: u16 = 37;
80const IFLA_PHYS_PORT_NAME: u16 = 38;
81const IFLA_PROTO_DOWN: u16 = 39;
82const IFLA_GSO_MAX_SEGS: u16 = 40;
83const IFLA_GSO_MAX_SIZE: u16 = 41;
84const IFLA_XDP: u16 = 43;
86const IFLA_EVENT: u16 = 44;
87const IFLA_NEW_NETNSID: u16 = 45;
88const IFLA_IF_NETNSID: u16 = 46;
89const IFLA_CARRIER_UP_COUNT: u16 = 47;
90const IFLA_CARRIER_DOWN_COUNT: u16 = 48;
91const IFLA_NEW_IFINDEX: u16 = 49;
92const IFLA_MIN_MTU: u16 = 50;
93const IFLA_MAX_MTU: u16 = 51;
94const IFLA_PROP_LIST: u16 = 52;
95const IFLA_PERM_ADDRESS: u16 = 54;
96const IFLA_PROTO_DOWN_REASON: u16 = 55;
97
98#[derive(Debug, PartialEq, Eq, Clone)]
109#[non_exhaustive]
110pub enum LinkAttribute {
111 VfInfoList(Vec<LinkVfInfo>),
112 VfPorts(Vec<LinkVfPort>),
113 PortSelf(LinkVfPort),
114 PhysPortId(LinkPhysId),
115 PhysSwitchId(LinkPhysId),
116 Xdp(Vec<LinkXdp>),
117 Event(LinkEvent),
118 NewNetnsId(i32),
119 IfNetnsId(i32),
120 CarrierUpCount(u32),
121 CarrierDownCount(u32),
122 NewIfIndex(i32),
123 LinkInfo(Vec<LinkInfo>),
124 Wireless(LinkWirelessEvent),
125 ProtoInfoBridge(Vec<LinkProtoInfoBridge>),
126 ProtoInfoInet6(Vec<LinkProtoInfoInet6>),
127 ProtoInfoUnknown(DefaultNla),
128 PropList(Vec<Prop>),
129 ProtoDownReason(Vec<LinkProtocolDownReason>),
130 Address(Vec<u8>),
131 Broadcast(Vec<u8>),
132 PermAddress(Vec<u8>),
135 IfName(String),
136 Qdisc(String),
137 IfAlias(String),
138 PhysPortName(String),
139 Mode(LinkMode),
140 Carrier(u8),
141 ProtoDown(u8),
142 Mtu(u32),
143 Link(u32),
144 Controller(u32),
145 TxQueueLen(u32),
146 NetNsPid(u32),
147 NumVf(u32),
148 Group(u32),
149 NetNsFd(RawFd),
150 ExtMask(Vec<LinkExtentMask>),
151 Promiscuity(u32),
152 NumTxQueues(u32),
153 NumRxQueues(u32),
154 CarrierChanges(u32),
155 GsoMaxSegs(u32),
156 GsoMaxSize(u32),
157 MinMtu(u32),
159 MaxMtu(u32),
161 LinkNetNsId(i32),
162 OperState(State),
163 Stats(Stats),
164 Stats64(Stats64),
165 Map(Map),
166 AfSpecUnspec(Vec<AfSpecUnspec>),
169 AfSpecBridge(Vec<AfSpecBridge>),
170 AfSpecUnknown(Vec<u8>),
171 Other(DefaultNla),
172}
173
174impl Nla for LinkAttribute {
175 fn value_len(&self) -> usize {
176 match self {
177 Self::VfInfoList(v) => v.as_slice().buffer_len(),
178 Self::VfPorts(v) => v.as_slice().buffer_len(),
179 Self::PortSelf(v) => v.buffer_len(),
180 Self::PhysPortId(v) => v.buffer_len(),
181 Self::PhysSwitchId(v) => v.buffer_len(),
182 Self::Event(v) => v.buffer_len(),
183 Self::Wireless(v) => v.buffer_len(),
184 Self::ProtoInfoBridge(v) => v.as_slice().buffer_len(),
185 Self::ProtoInfoInet6(v) => v.as_slice().buffer_len(),
186 Self::ProtoDownReason(v) => v.as_slice().buffer_len(),
187
188 Self::Address(bytes)
189 | Self::Broadcast(bytes)
190 | Self::PermAddress(bytes)
191 | Self::AfSpecUnknown(bytes) => bytes.len(),
192
193 Self::IfName(string)
194 | Self::Qdisc(string)
195 | Self::IfAlias(string)
196 | Self::PhysPortName(string) => string.len() + 1,
197
198 Self::Mode(_) => 1,
199 Self::Carrier(_) | Self::ProtoDown(_) => 1,
200
201 Self::Mtu(_)
202 | Self::NewNetnsId(_)
203 | Self::IfNetnsId(_)
204 | Self::Link(_)
205 | Self::Controller(_)
206 | Self::TxQueueLen(_)
207 | Self::NetNsPid(_)
208 | Self::NumVf(_)
209 | Self::Group(_)
210 | Self::NetNsFd(_)
211 | Self::ExtMask(_)
212 | Self::Promiscuity(_)
213 | Self::NumTxQueues(_)
214 | Self::NumRxQueues(_)
215 | Self::CarrierChanges(_)
216 | Self::GsoMaxSegs(_)
217 | Self::GsoMaxSize(_)
218 | Self::LinkNetNsId(_)
219 | Self::MinMtu(_)
220 | Self::CarrierUpCount(_)
221 | Self::CarrierDownCount(_)
222 | Self::NewIfIndex(_)
223 | Self::MaxMtu(_) => 4,
224
225 Self::OperState(_) => 1,
226 Self::Stats(_) => LINK_STATS_LEN,
227 Self::Stats64(_) => LINK_STATS64_LEN,
228 Self::Map(nla) => nla.buffer_len(),
229 Self::LinkInfo(nlas) => nlas.as_slice().buffer_len(),
230 Self::Xdp(nlas) => nlas.as_slice().buffer_len(),
231 Self::PropList(nlas) => nlas.as_slice().buffer_len(),
232 Self::AfSpecUnspec(nlas) => nlas.as_slice().buffer_len(),
233 Self::AfSpecBridge(nlas) => nlas.as_slice().buffer_len(),
234 Self::ProtoInfoUnknown(attr) => attr.value_len(),
235 Self::Other(attr) => attr.value_len(),
236 }
237 }
238
239 fn emit_value(&self, buffer: &mut [u8]) {
240 match self {
241 Self::VfInfoList(v) => v.as_slice().emit(buffer),
242 Self::VfPorts(v) => v.as_slice().emit(buffer),
243 Self::PortSelf(v) => v.emit(buffer),
244 Self::PhysPortId(v) => v.emit(buffer),
245 Self::PhysSwitchId(v) => v.emit(buffer),
246 Self::Event(v) => v.emit(buffer),
247 Self::Wireless(v) => v.emit(buffer),
248 Self::ProtoInfoBridge(v) => v.as_slice().emit(buffer),
249 Self::ProtoInfoInet6(v) => v.as_slice().emit(buffer),
250 Self::ProtoDownReason(v) => v.as_slice().emit(buffer),
251 Self::Address(bytes)
252 | Self::Broadcast(bytes)
253 | Self::PermAddress(bytes)
254 | Self::AfSpecUnknown(bytes) => {
255 buffer.copy_from_slice(bytes.as_slice())
256 }
257
258 Self::IfName(string)
259 | Self::Qdisc(string)
260 | Self::IfAlias(string)
261 | Self::PhysPortName(string) => {
262 buffer[..string.len()].copy_from_slice(string.as_bytes());
263 buffer[string.len()] = 0;
264 }
265 Self::Mode(v) => buffer[0] = (*v).into(),
266
267 Self::Carrier(val) | Self::ProtoDown(val) => buffer[0] = *val,
268
269 Self::Mtu(value)
270 | Self::Link(value)
271 | Self::Controller(value)
272 | Self::TxQueueLen(value)
273 | Self::NetNsPid(value)
274 | Self::NumVf(value)
275 | Self::Group(value)
276 | Self::Promiscuity(value)
277 | Self::NumTxQueues(value)
278 | Self::NumRxQueues(value)
279 | Self::CarrierChanges(value)
280 | Self::CarrierUpCount(value)
281 | Self::CarrierDownCount(value)
282 | Self::GsoMaxSegs(value)
283 | Self::GsoMaxSize(value)
284 | Self::MinMtu(value)
285 | Self::MaxMtu(value) => emit_u32(buffer, *value).unwrap(),
286
287 Self::ExtMask(value) => {
288 emit_u32(buffer, u32::from(&VecLinkExtentMask(value.to_vec())))
289 .unwrap()
290 }
291
292 Self::LinkNetNsId(v)
293 | Self::NetNsFd(v)
294 | Self::NewNetnsId(v)
295 | Self::NewIfIndex(v)
296 | Self::IfNetnsId(v) => emit_i32(buffer, *v).unwrap(),
297 Self::Stats(nla) => nla.emit(buffer),
298 Self::Map(nla) => nla.emit(buffer),
299 Self::Stats64(nla) => nla.emit(buffer),
300 Self::OperState(state) => buffer[0] = (*state).into(),
301 Self::LinkInfo(nlas) => nlas.as_slice().emit(buffer),
302 Self::Xdp(nlas) => nlas.as_slice().emit(buffer),
303 Self::PropList(nlas) => nlas.as_slice().emit(buffer),
304 Self::AfSpecUnspec(nlas) => nlas.as_slice().emit(buffer),
305 Self::AfSpecBridge(nlas) => nlas.as_slice().emit(buffer),
306 Self::ProtoInfoUnknown(attr) | Self::Other(attr) => {
307 attr.emit_value(buffer)
308 }
309 }
310 }
311
312 fn kind(&self) -> u16 {
313 match self {
314 Self::VfInfoList(_) => IFLA_VFINFO_LIST,
315 Self::VfPorts(_) => IFLA_VF_PORTS,
316 Self::PortSelf(_) => IFLA_PORT_SELF,
317 Self::PhysPortId(_) => IFLA_PHYS_PORT_ID,
318 Self::PhysSwitchId(_) => IFLA_PHYS_SWITCH_ID,
319 Self::LinkInfo(_) => IFLA_LINKINFO,
320 Self::Wireless(_) => IFLA_WIRELESS,
321 Self::ProtoInfoBridge(_) | Self::ProtoInfoInet6(_) => IFLA_PROTINFO,
322 Self::ProtoInfoUnknown(attr) => attr.kind(),
323 Self::Xdp(_) => IFLA_XDP,
324 Self::Event(_) => IFLA_EVENT,
325 Self::NewNetnsId(_) => IFLA_NEW_NETNSID,
326 Self::IfNetnsId(_) => IFLA_IF_NETNSID,
327 Self::CarrierUpCount(_) => IFLA_CARRIER_UP_COUNT,
328 Self::CarrierDownCount(_) => IFLA_CARRIER_DOWN_COUNT,
329 Self::NewIfIndex(_) => IFLA_NEW_IFINDEX,
330 Self::PropList(_) => IFLA_PROP_LIST | NLA_F_NESTED,
331 Self::ProtoDownReason(_) => IFLA_PROTO_DOWN_REASON,
332 Self::Address(_) => IFLA_ADDRESS,
333 Self::Broadcast(_) => IFLA_BROADCAST,
334 Self::PermAddress(_) => IFLA_PERM_ADDRESS,
335 Self::IfName(_) => IFLA_IFNAME,
336 Self::Qdisc(_) => IFLA_QDISC,
337 Self::IfAlias(_) => IFLA_IFALIAS,
338 Self::PhysPortName(_) => IFLA_PHYS_PORT_NAME,
339 Self::Mode(_) => IFLA_LINKMODE,
340 Self::Carrier(_) => IFLA_CARRIER,
341 Self::ProtoDown(_) => IFLA_PROTO_DOWN,
342 Self::Mtu(_) => IFLA_MTU,
343 Self::Link(_) => IFLA_LINK,
344 Self::Controller(_) => IFLA_MASTER,
345 Self::TxQueueLen(_) => IFLA_TXQLEN,
346 Self::NetNsPid(_) => IFLA_NET_NS_PID,
347 Self::NumVf(_) => IFLA_NUM_VF,
348 Self::Group(_) => IFLA_GROUP,
349 Self::NetNsFd(_) => IFLA_NET_NS_FD,
350 Self::ExtMask(_) => IFLA_EXT_MASK,
351 Self::Promiscuity(_) => IFLA_PROMISCUITY,
352 Self::NumTxQueues(_) => IFLA_NUM_TX_QUEUES,
353 Self::NumRxQueues(_) => IFLA_NUM_RX_QUEUES,
354 Self::CarrierChanges(_) => IFLA_CARRIER_CHANGES,
355 Self::GsoMaxSegs(_) => IFLA_GSO_MAX_SEGS,
356 Self::GsoMaxSize(_) => IFLA_GSO_MAX_SIZE,
357 Self::MinMtu(_) => IFLA_MIN_MTU,
358 Self::MaxMtu(_) => IFLA_MAX_MTU,
359 Self::LinkNetNsId(_) => IFLA_LINK_NETNSID,
360 Self::OperState(_) => IFLA_OPERSTATE,
361 Self::Map(_) => IFLA_MAP,
362 Self::Stats(_) => IFLA_STATS,
363 Self::Stats64(_) => IFLA_STATS64,
364 Self::AfSpecUnspec(_)
365 | Self::AfSpecBridge(_)
366 | Self::AfSpecUnknown(_) => IFLA_AF_SPEC,
367 Self::Other(attr) => attr.kind(),
368 }
369 }
370}
371
372impl<'a, T: AsRef<[u8]> + ?Sized>
373 ParseableParametrized<NlaBuffer<&'a T>, AddressFamily> for LinkAttribute
374{
375 fn parse_with_param(
376 buf: &NlaBuffer<&'a T>,
377 interface_family: AddressFamily,
378 ) -> Result<Self, DecodeError> {
379 let payload = buf.value();
380 Ok(match buf.kind() {
381 IFLA_VFINFO_LIST => {
382 let err =
383 |payload| format!("invalid IFLA_VFINFO_LIST {payload:?}");
384 if !payload.is_empty() {
385 Self::VfInfoList(
386 VecLinkVfInfo::parse(
387 &NlaBuffer::new_checked(payload)
388 .context(err(payload))?,
389 )
390 .context(err(payload))?
391 .0,
392 )
393 } else {
394 Self::VfInfoList(vec![])
397 }
398 }
399 IFLA_VF_PORTS => {
400 let err =
401 |payload| format!("invalid IFLA_VF_PORTS {payload:?}");
402 Self::VfPorts(
403 VecLinkVfPort::parse(
404 &NlaBuffer::new_checked(payload)
405 .context(err(payload))?,
406 )
407 .context(err(payload))?
408 .0,
409 )
410 }
411 IFLA_PORT_SELF => {
412 let err =
413 |payload| format!("invalid IFLA_PORT_SELF {payload:?}");
414 Self::PortSelf(
415 LinkVfPort::parse(
416 &NlaBuffer::new_checked(payload)
417 .context(err(payload))?,
418 )
419 .context(err(payload))?,
420 )
421 }
422 IFLA_PHYS_PORT_ID => {
423 Self::PhysPortId(LinkPhysId::parse(payload).context(
424 format!("invalid IFLA_PHYS_PORT_ID value {payload:?}"),
425 )?)
426 }
427 IFLA_PHYS_SWITCH_ID => {
428 Self::PhysSwitchId(LinkPhysId::parse(payload).context(
429 format!("invalid IFLA_PHYS_SWITCH_ID value {payload:?}"),
430 )?)
431 }
432 IFLA_WIRELESS => Self::Wireless(
433 LinkWirelessEvent::parse(payload)
434 .context(format!("invalid IFLA_WIRELESS {payload:?}"))?,
435 ),
436 IFLA_PROTINFO => {
437 let err = |payload| {
438 format!("invalid IFLA_PROTINFO for AF_INET6 {payload:?}")
439 };
440 match interface_family {
441 AddressFamily::Inet6 => Self::ProtoInfoInet6(
442 VecLinkProtoInfoInet6::parse(
443 &NlaBuffer::new_checked(payload)
444 .context(err(payload))?,
445 )
446 .context(err(payload))?
447 .0,
448 ),
449 #[cfg(any(
450 target_os = "linux",
451 target_os = "fuchsia",
452 target_os = "android"
453 ))]
454 AddressFamily::Bridge => Self::ProtoInfoBridge(
455 VecLinkProtoInfoBridge::parse(&NlaBuffer::new_checked(
456 payload,
457 )?)
458 .context(format!(
459 "invalid IFLA_PROTINFO for AF_INET6 {payload:?}"
460 ))?
461 .0,
462 ),
463 _ => Self::ProtoInfoUnknown(
464 DefaultNla::parse(buf).context(format!(
465 "invalid IFLA_PROTINFO for {interface_family:?}: \
466 {payload:?}"
467 ))?,
468 ),
469 }
470 }
471 IFLA_EVENT => Self::Event(
472 LinkEvent::parse(payload)
473 .context(format!("invalid IFLA_EVENT {payload:?}"))?,
474 ),
475 IFLA_NEW_NETNSID => Self::NewNetnsId(
476 parse_i32(payload).context("invalid IFLA_NEW_NETNSID value")?,
477 ),
478 IFLA_IF_NETNSID => Self::IfNetnsId(
479 parse_i32(payload).context("invalid IFLA_IF_NETNSID value")?,
480 ),
481 IFLA_CARRIER_UP_COUNT => Self::CarrierUpCount(
482 parse_u32(payload)
483 .context("invalid IFLA_CARRIER_UP_COUNT value")?,
484 ),
485 IFLA_CARRIER_DOWN_COUNT => Self::CarrierDownCount(
486 parse_u32(payload)
487 .context("invalid IFLA_CARRIER_DOWN_COUNT value")?,
488 ),
489 IFLA_NEW_IFINDEX => Self::NewIfIndex(
490 parse_i32(payload).context("invalid IFLA_NEW_IFINDEX value")?,
491 ),
492
493 IFLA_PROP_LIST => {
494 let error_msg = "invalid IFLA_PROP_LIST value";
495 let mut nlas = vec![];
496 for nla in NlasIterator::new(payload) {
497 let nla = &nla.context(error_msg)?;
498 let parsed = Prop::parse(nla).context(error_msg)?;
499 nlas.push(parsed);
500 }
501 Self::PropList(nlas)
502 }
503 IFLA_PROTO_DOWN_REASON => {
504 let mut nlas = vec![];
505 for nla in NlasIterator::new(payload) {
506 let nla =
507 &nla.context("invalid IFLA_PROTO_DOWN_REASON value")?;
508 let parsed = LinkProtocolDownReason::parse(nla)?;
509 nlas.push(parsed);
510 }
511 Self::ProtoDownReason(nlas)
512 }
513 IFLA_ADDRESS => Self::Address(payload.to_vec()),
517 IFLA_BROADCAST => Self::Broadcast(payload.to_vec()),
518 IFLA_PERM_ADDRESS => Self::PermAddress(payload.to_vec()),
519 IFLA_IFNAME => Self::IfName(
521 parse_string(payload).context("invalid IFLA_IFNAME value")?,
522 ),
523 IFLA_QDISC => Self::Qdisc(
524 parse_string(payload).context("invalid IFLA_QDISC value")?,
525 ),
526 IFLA_IFALIAS => Self::IfAlias(
527 parse_string(payload).context("invalid IFLA_IFALIAS value")?,
528 ),
529 IFLA_PHYS_PORT_NAME => Self::PhysPortName(
530 parse_string(payload)
531 .context("invalid IFLA_PHYS_PORT_NAME value")?,
532 ),
533 IFLA_LINKMODE => Self::Mode(LinkMode::from(
534 parse_u8(payload).context("invalid IFLA_LINKMODE value")?,
535 )),
536 IFLA_CARRIER => Self::Carrier(
537 parse_u8(payload).context("invalid IFLA_CARRIER value")?,
538 ),
539 IFLA_PROTO_DOWN => Self::ProtoDown(
540 parse_u8(payload).context("invalid IFLA_PROTO_DOWN value")?,
541 ),
542
543 IFLA_MTU => {
544 Self::Mtu(parse_u32(payload).context("invalid IFLA_MTU value")?)
545 }
546 IFLA_LINK => Self::Link(
547 parse_u32(payload).context("invalid IFLA_LINK value")?,
548 ),
549 IFLA_MASTER => Self::Controller(
550 parse_u32(payload).context("invalid IFLA_MASTER value")?,
551 ),
552 IFLA_TXQLEN => Self::TxQueueLen(
553 parse_u32(payload).context("invalid IFLA_TXQLEN value")?,
554 ),
555 IFLA_NET_NS_PID => Self::NetNsPid(
556 parse_u32(payload).context("invalid IFLA_NET_NS_PID value")?,
557 ),
558 IFLA_NUM_VF => Self::NumVf(
559 parse_u32(payload).context("invalid IFLA_NUM_VF value")?,
560 ),
561 IFLA_GROUP => Self::Group(
562 parse_u32(payload).context("invalid IFLA_GROUP value")?,
563 ),
564 IFLA_NET_NS_FD => Self::NetNsFd(
565 parse_i32(payload).context("invalid IFLA_NET_NS_FD value")?,
566 ),
567 IFLA_EXT_MASK => Self::ExtMask(
568 VecLinkExtentMask::from(
569 parse_u32(payload)
570 .context("invalid IFLA_EXT_MASK value")?,
571 )
572 .0,
573 ),
574 IFLA_PROMISCUITY => Self::Promiscuity(
575 parse_u32(payload).context("invalid IFLA_PROMISCUITY value")?,
576 ),
577 IFLA_NUM_TX_QUEUES => Self::NumTxQueues(
578 parse_u32(payload)
579 .context("invalid IFLA_NUM_TX_QUEUES value")?,
580 ),
581 IFLA_NUM_RX_QUEUES => Self::NumRxQueues(
582 parse_u32(payload)
583 .context("invalid IFLA_NUM_RX_QUEUES value")?,
584 ),
585 IFLA_CARRIER_CHANGES => Self::CarrierChanges(
586 parse_u32(payload)
587 .context("invalid IFLA_CARRIER_CHANGES value")?,
588 ),
589 IFLA_GSO_MAX_SEGS => Self::GsoMaxSegs(
590 parse_u32(payload)
591 .context("invalid IFLA_GSO_MAX_SEGS value")?,
592 ),
593 IFLA_GSO_MAX_SIZE => Self::GsoMaxSize(
594 parse_u32(payload)
595 .context("invalid IFLA_GSO_MAX_SIZE value")?,
596 ),
597 IFLA_MIN_MTU => Self::MinMtu(
598 parse_u32(payload).context("invalid IFLA_MIN_MTU value")?,
599 ),
600 IFLA_MAX_MTU => Self::MaxMtu(
601 parse_u32(payload).context("invalid IFLA_MAX_MTU value")?,
602 ),
603 IFLA_LINK_NETNSID => Self::LinkNetNsId(
604 parse_i32(payload)
605 .context("invalid IFLA_LINK_NETNSID value")?,
606 ),
607 IFLA_OPERSTATE => Self::OperState(
608 parse_u8(payload)
609 .context("invalid IFLA_OPERSTATE value")?
610 .into(),
611 ),
612 IFLA_MAP => {
613 let err =
614 |payload| format!("Invalid IFLA_MAP value {payload:?}");
615 Self::Map(
616 super::Map::parse(
617 &MapBuffer::new_checked(payload)
618 .context(err(payload))?,
619 )
620 .context(err(payload))?,
621 )
622 }
623 IFLA_STATS => Self::Stats(
624 super::Stats::parse(&StatsBuffer::new(
625 expand_buffer_if_small(
626 payload,
627 LINK_STATS_LEN,
628 "IFLA_STATS",
629 )
630 .as_slice(),
631 ))
632 .context(format!("Invalid IFLA_STATS value {payload:?}"))?,
633 ),
634 IFLA_STATS64 => {
635 let payload = expand_buffer_if_small(
636 payload,
637 LINK_STATS64_LEN,
638 "IFLA_STATS64",
639 );
640 Self::Stats64(
641 super::Stats64::parse(&Stats64Buffer::new(
642 payload.as_slice(),
643 ))
644 .context(format!(
645 "Invalid IFLA_STATS64 value {payload:?}"
646 ))?,
647 )
648 }
649 IFLA_AF_SPEC => match interface_family {
650 AddressFamily::Unspec => {
651 let err = "invalid IFLA_AF_SPEC value for AF_UNSPEC";
652 Self::AfSpecUnspec(
653 VecAfSpecUnspec::parse(&NlaBuffer::new(&buf.value()))
654 .context(err)?
655 .0,
656 )
657 }
658 #[cfg(any(
659 target_os = "linux",
660 target_os = "fuchsia",
661 target_os = "android"
662 ))]
663 AddressFamily::Bridge => {
664 let err = "invalid IFLA_AF_SPEC value for AF_BRIDGE";
665 Self::AfSpecBridge(
666 VecAfSpecBridge::parse(
667 &NlaBuffer::new_checked(&buf.value())
668 .context(err)?,
669 )
670 .context(err)?
671 .0,
672 )
673 }
674 _ => Self::AfSpecUnknown(payload.to_vec()),
675 },
676 IFLA_LINKINFO => {
677 let err = "invalid IFLA_LINKINFO value";
678 Self::LinkInfo(
679 VecLinkInfo::parse(
680 &NlaBuffer::new_checked(&buf.value()).context(err)?,
681 )
682 .context(err)?
683 .0,
684 )
685 }
686 IFLA_XDP => {
687 let err = "invalid IFLA_XDP value";
688 let buf = NlaBuffer::new_checked(payload).context(err)?;
689 Self::Xdp(VecLinkXdp::parse(&buf).context(err)?.0)
690 }
691 kind => Self::Other(
692 DefaultNla::parse(buf)
693 .context(format!("unknown NLA type {kind}"))?,
694 ),
695 })
696 }
697}