netlink_packet_route/rtnl/link/nlas/
af_spec_bridge.rs1use std::convert::TryFrom;
4
5use anyhow::Context;
6use netlink_packet_utils::{
7 nla::{self, DefaultNla, NlaBuffer},
8 parsers::parse_u16,
9 traits::Parseable,
10 DecodeError,
11};
12
13use crate::constants::*;
14
15use byteorder::{ByteOrder, NativeEndian};
16
17#[derive(Clone, Eq, PartialEq, Debug)]
18#[non_exhaustive]
19pub enum AfSpecBridge {
20 Flags(u16),
21 VlanInfo(BridgeVlanInfo),
22 Other(DefaultNla),
23}
24
25impl nla::Nla for AfSpecBridge {
26 fn value_len(&self) -> usize {
27 use self::AfSpecBridge::*;
28 match *self {
29 VlanInfo(_) => 4,
30 Flags(_) => 2,
31 Other(ref nla) => nla.value_len(),
32 }
33 }
34
35 fn emit_value(&self, buffer: &mut [u8]) {
36 use self::AfSpecBridge::*;
37 match *self {
38 Flags(value) => NativeEndian::write_u16(buffer, value),
39 VlanInfo(ref info) => {
40 buffer[..4].copy_from_slice(<[u8; 4]>::from(info).as_slice())
41 }
42 Other(ref nla) => nla.emit_value(buffer),
43 }
44 }
45
46 fn kind(&self) -> u16 {
47 use self::AfSpecBridge::*;
48 match *self {
49 Flags(_) => IFLA_BRIDGE_FLAGS,
50 VlanInfo(_) => IFLA_BRIDGE_VLAN_INFO,
51 Other(ref nla) => nla.kind(),
52 }
53 }
54}
55
56impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for AfSpecBridge {
57 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
58 use self::AfSpecBridge::*;
59
60 let payload = buf.value();
61 Ok(match buf.kind() {
62 IFLA_BRIDGE_VLAN_INFO => VlanInfo(
63 BridgeVlanInfo::try_from(payload)
64 .context("Invalid IFLA_BRIDGE_VLAN_INFO value")?,
65 ),
66 IFLA_BRIDGE_FLAGS => Flags(
67 parse_u16(payload)
68 .context("invalid IFLA_BRIDGE_FLAGS value")?,
69 ),
70 kind => Other(
71 DefaultNla::parse(buf)
72 .context(format!("Unknown NLA type {kind}"))?,
73 ),
74 })
75 }
76}
77
78#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
79#[non_exhaustive]
80pub struct BridgeVlanInfo {
81 pub flags: u16,
82 pub vid: u16,
83}
84
85impl From<&BridgeVlanInfo> for [u8; 4] {
86 fn from(d: &BridgeVlanInfo) -> Self {
87 let mut ret = [0u8; 4];
88 NativeEndian::write_u16(&mut ret[0..2], d.flags);
89 NativeEndian::write_u16(&mut ret[2..4], d.vid);
90 ret
91 }
92}
93
94impl TryFrom<&[u8]> for BridgeVlanInfo {
95 type Error = DecodeError;
96 fn try_from(raw: &[u8]) -> Result<Self, DecodeError> {
97 if raw.len() == 4 {
98 Ok(Self {
99 flags: parse_u16(&raw[0..2]).context(format!(
100 "Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
101 ))?,
102 vid: parse_u16(&raw[2..4]).context(format!(
103 "Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
104 ))?,
105 })
106 } else {
107 Err(DecodeError::from(format!(
108 "Invalid IFLA_BRIDGE_VLAN_INFO value, expecting [u8;4], but got {raw:?}"
109 )))
110 }
111 }
112}