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