netlink_packet_route/link/link_info/
hsr.rs
1use anyhow::Context;
4use byteorder::{ByteOrder, NativeEndian};
5use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
6use netlink_packet_utils::parsers::{parse_mac, parse_u16, parse_u32, parse_u8};
7use netlink_packet_utils::traits::Parseable;
8use netlink_packet_utils::DecodeError;
9
10const IFLA_HSR_PORT1: u16 = 1;
12const IFLA_HSR_PORT2: u16 = 2;
14const IFLA_HSR_MULTICAST_SPEC: u16 = 3;
15const IFLA_HSR_SUPERVISION_ADDR: u16 = 4;
16const IFLA_HSR_SEQ_NR: u16 = 5;
17const IFLA_HSR_VERSION: u16 = 6;
18const IFLA_HSR_PROTOCOL: u16 = 7;
19
20#[derive(Debug, PartialEq, Eq, Clone)]
21#[non_exhaustive]
22pub enum InfoHsr {
23 Port1(u32),
24 Port2(u32),
25 MulticastSpec(u8),
26 SupervisionAddr([u8; 6]),
27 Version(u8),
28 SeqNr(u16),
29 Protocol(HsrProtocol),
30 Other(DefaultNla),
31}
32
33impl Nla for InfoHsr {
34 fn value_len(&self) -> usize {
35 use self::InfoHsr::*;
36 match self {
37 SupervisionAddr(_) => 6,
38 Port1(_) | Port2(_) => 4,
39 SeqNr(_) => 2,
40 MulticastSpec(_) | Version(_) | Protocol(_) => 1,
41 Other(nla) => nla.value_len(),
42 }
43 }
44
45 fn emit_value(&self, buffer: &mut [u8]) {
46 use self::InfoHsr::*;
47 match self {
48 Port1(value) | Port2(value) => NativeEndian::write_u32(buffer, *value),
49 MulticastSpec(value) | Version(value) => buffer[0] = *value,
50 SeqNr(value) => NativeEndian::write_u16(buffer, *value),
51 Protocol(value) => buffer[0] = (*value).into(),
52 SupervisionAddr(ref value) => buffer.copy_from_slice(&value[..]),
53 Other(nla) => nla.emit_value(buffer),
54 }
55 }
56
57 fn kind(&self) -> u16 {
58 use self::InfoHsr::*;
59 match self {
60 Port1(_) => IFLA_HSR_PORT1,
61 Port2(_) => IFLA_HSR_PORT2,
62 MulticastSpec(_) => IFLA_HSR_MULTICAST_SPEC,
63 SupervisionAddr(_) => IFLA_HSR_SUPERVISION_ADDR,
64 SeqNr(_) => IFLA_HSR_SEQ_NR,
65 Version(_) => IFLA_HSR_VERSION,
66 Protocol(_) => IFLA_HSR_PROTOCOL,
67 Other(nla) => nla.kind(),
68 }
69 }
70}
71
72impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoHsr {
73 type Error = DecodeError;
74 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
75 use self::InfoHsr::*;
76 let payload = buf.value();
77 Ok(match buf.kind() {
78 IFLA_HSR_PORT1 => Port1(parse_u32(payload).context("invalid IFLA_HSR_PORT1 value")?),
79 IFLA_HSR_PORT2 => Port2(parse_u32(payload).context("invalid IFLA_HSR_PORT2 value")?),
80 IFLA_HSR_MULTICAST_SPEC => {
81 MulticastSpec(parse_u8(payload).context("invalid IFLA_HSR_MULTICAST_SPEC value")?)
82 }
83 IFLA_HSR_SUPERVISION_ADDR => SupervisionAddr(
84 parse_mac(payload).context("invalid IFLA_HSR_SUPERVISION_ADDR value")?,
85 ),
86 IFLA_HSR_SEQ_NR => SeqNr(parse_u16(payload).context("invalid IFLA_HSR_SEQ_NR value")?),
87 IFLA_HSR_VERSION => {
88 Version(parse_u8(payload).context("invalid IFLA_HSR_VERSION value")?)
89 }
90 IFLA_HSR_PROTOCOL => {
91 Protocol(parse_u8(payload).context("invalid IFLA_HSR_PROTOCOL value")?.into())
92 }
93 kind => Other(DefaultNla::parse(buf).context(format!("unknown NLA type {kind}"))?),
94 })
95 }
96}
97
98const HSR_PROTOCOL_HSR: u8 = 0;
99const HSR_PROTOCOL_PRP: u8 = 1;
100
101#[derive(Debug, PartialEq, Eq, Clone, Copy)]
102#[non_exhaustive]
103#[repr(u8)]
104pub enum HsrProtocol {
105 Hsr = HSR_PROTOCOL_HSR,
106 Prp = HSR_PROTOCOL_PRP,
107 Other(u8),
108}
109
110impl From<u8> for HsrProtocol {
111 fn from(d: u8) -> Self {
112 match d {
113 HSR_PROTOCOL_HSR => Self::Hsr,
114 HSR_PROTOCOL_PRP => Self::Prp,
115 _ => Self::Other(d),
116 }
117 }
118}
119
120impl From<HsrProtocol> for u8 {
121 fn from(d: HsrProtocol) -> Self {
122 match d {
123 HsrProtocol::Hsr => HSR_PROTOCOL_HSR,
124 HsrProtocol::Prp => HSR_PROTOCOL_PRP,
125 HsrProtocol::Other(value) => value,
126 }
127 }
128}
129
130impl std::fmt::Display for HsrProtocol {
131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 match self {
133 Self::Hsr => write!(f, "hsr"),
134 Self::Prp => write!(f, "prp"),
135 Self::Other(d) => write!(f, "{}", d),
136 }
137 }
138}