netlink_packet_route/link/link_info/
hsr.rs

1// SPDX-License-Identifier: MIT
2
3use 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
10// Kernel constant name is IFLA_HSR_SLAVE1
11const IFLA_HSR_PORT1: u16 = 1;
12// Kernel constant name is IFLA_HSR_SLAVE2
13const 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}