netlink_packet_route/link/link_info/
hsr.rs

1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::{
4    emit_u16, emit_u32, parse_mac, parse_u16, parse_u32, parse_u8, DecodeError,
5    DefaultNla, ErrorContext, Nla, NlaBuffer, Parseable,
6};
7
8// Kernel constant name is IFLA_HSR_SLAVE1
9const IFLA_HSR_PORT1: u16 = 1;
10// Kernel constant name is IFLA_HSR_SLAVE2
11const IFLA_HSR_PORT2: u16 = 2;
12const IFLA_HSR_MULTICAST_SPEC: u16 = 3;
13const IFLA_HSR_SUPERVISION_ADDR: u16 = 4;
14const IFLA_HSR_SEQ_NR: u16 = 5;
15const IFLA_HSR_VERSION: u16 = 6;
16const IFLA_HSR_PROTOCOL: u16 = 7;
17const IFLA_HSR_INTERLINK: u16 = 8;
18
19#[derive(Debug, PartialEq, Eq, Clone)]
20#[non_exhaustive]
21pub enum InfoHsr {
22    Port1(u32),
23    Port2(u32),
24    Interlink(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(_) | Interlink(_) => 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) | Interlink(value) => {
49                emit_u32(buffer, *value).unwrap()
50            }
51            MulticastSpec(value) | Version(value) => buffer[0] = *value,
52            SeqNr(value) => emit_u16(buffer, *value).unwrap(),
53            Protocol(value) => buffer[0] = (*value).into(),
54            SupervisionAddr(ref value) => buffer.copy_from_slice(&value[..]),
55            Other(nla) => nla.emit_value(buffer),
56        }
57    }
58
59    fn kind(&self) -> u16 {
60        use self::InfoHsr::*;
61        match self {
62            Port1(_) => IFLA_HSR_PORT1,
63            Port2(_) => IFLA_HSR_PORT2,
64            Interlink(_) => IFLA_HSR_INTERLINK,
65            MulticastSpec(_) => IFLA_HSR_MULTICAST_SPEC,
66            SupervisionAddr(_) => IFLA_HSR_SUPERVISION_ADDR,
67            SeqNr(_) => IFLA_HSR_SEQ_NR,
68            Version(_) => IFLA_HSR_VERSION,
69            Protocol(_) => IFLA_HSR_PROTOCOL,
70            Other(nla) => nla.kind(),
71        }
72    }
73}
74
75impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoHsr {
76    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
77        use self::InfoHsr::*;
78        let payload = buf.value();
79        Ok(match buf.kind() {
80            IFLA_HSR_PORT1 => Port1(
81                parse_u32(payload).context("invalid IFLA_HSR_PORT1 value")?,
82            ),
83            IFLA_HSR_PORT2 => Port2(
84                parse_u32(payload).context("invalid IFLA_HSR_PORT2 value")?,
85            ),
86            IFLA_HSR_INTERLINK => Interlink(
87                parse_u32(payload)
88                    .context("invalid IFLA_HSR_INTERLINK value")?,
89            ),
90            IFLA_HSR_MULTICAST_SPEC => MulticastSpec(
91                parse_u8(payload)
92                    .context("invalid IFLA_HSR_MULTICAST_SPEC value")?,
93            ),
94            IFLA_HSR_SUPERVISION_ADDR => SupervisionAddr(
95                parse_mac(payload)
96                    .context("invalid IFLA_HSR_SUPERVISION_ADDR value")?,
97            ),
98            IFLA_HSR_SEQ_NR => SeqNr(
99                parse_u16(payload).context("invalid IFLA_HSR_SEQ_NR value")?,
100            ),
101            IFLA_HSR_VERSION => Version(
102                parse_u8(payload).context("invalid IFLA_HSR_VERSION value")?,
103            ),
104            IFLA_HSR_PROTOCOL => Protocol(
105                parse_u8(payload)
106                    .context("invalid IFLA_HSR_PROTOCOL value")?
107                    .into(),
108            ),
109            kind => Other(
110                DefaultNla::parse(buf)
111                    .context(format!("unknown NLA type {kind}"))?,
112            ),
113        })
114    }
115}
116
117const HSR_PROTOCOL_HSR: u8 = 0;
118const HSR_PROTOCOL_PRP: u8 = 1;
119
120#[derive(Debug, PartialEq, Eq, Clone, Copy)]
121#[non_exhaustive]
122#[repr(u8)]
123pub enum HsrProtocol {
124    Hsr = HSR_PROTOCOL_HSR,
125    Prp = HSR_PROTOCOL_PRP,
126    Other(u8),
127}
128
129impl From<u8> for HsrProtocol {
130    fn from(d: u8) -> Self {
131        match d {
132            HSR_PROTOCOL_HSR => Self::Hsr,
133            HSR_PROTOCOL_PRP => Self::Prp,
134            _ => Self::Other(d),
135        }
136    }
137}
138
139impl From<HsrProtocol> for u8 {
140    fn from(d: HsrProtocol) -> Self {
141        match d {
142            HsrProtocol::Hsr => HSR_PROTOCOL_HSR,
143            HsrProtocol::Prp => HSR_PROTOCOL_PRP,
144            HsrProtocol::Other(value) => value,
145        }
146    }
147}
148
149impl std::fmt::Display for HsrProtocol {
150    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151        match self {
152            Self::Hsr => write!(f, "hsr"),
153            Self::Prp => write!(f, "prp"),
154            Self::Other(d) => write!(f, "{d}"),
155        }
156    }
157}