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