netlink_packet_route/neighbour_table/
attribute.rs1use netlink_packet_core::{
4 emit_u32, emit_u64, parse_string, parse_u32, parse_u64, DecodeError,
5 DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer, Parseable,
6};
7
8use super::{
9 param::VecNeighbourTableParameter, NeighbourTableConfig,
10 NeighbourTableConfigBuffer, NeighbourTableParameter, NeighbourTableStats,
11 NeighbourTableStatsBuffer,
12};
13
14const NDTA_NAME: u16 = 1;
15const NDTA_THRESH1: u16 = 2;
16const NDTA_THRESH2: u16 = 3;
17const NDTA_THRESH3: u16 = 4;
18const NDTA_CONFIG: u16 = 5;
19const NDTA_PARMS: u16 = 6;
20const NDTA_STATS: u16 = 7;
21const NDTA_GC_INTERVAL: u16 = 8;
22
23#[derive(Debug, PartialEq, Eq, Clone)]
24#[non_exhaustive]
25pub enum NeighbourTableAttribute {
26 Parms(Vec<NeighbourTableParameter>),
27 Name(String),
28 Threshold1(u32),
29 Threshold2(u32),
30 Threshold3(u32),
31 Config(NeighbourTableConfig),
32 Stats(NeighbourTableStats),
33 GcInterval(u64),
34 Other(DefaultNla),
35}
36
37impl Nla for NeighbourTableAttribute {
38 fn value_len(&self) -> usize {
39 match self {
40 Self::Parms(v) => v.as_slice().buffer_len(),
41 Self::Stats(v) => v.buffer_len(),
42 Self::Config(v) => v.buffer_len(),
43 Self::Name(s) => s.len() + 1,
45 Self::Threshold1(_) | Self::Threshold2(_) | Self::Threshold3(_) => {
46 4
47 }
48 Self::GcInterval(_) => 8,
49 Self::Other(attr) => attr.value_len(),
50 }
51 }
52
53 fn emit_value(&self, buffer: &mut [u8]) {
54 match self {
55 Self::Parms(v) => v.as_slice().emit(buffer),
56 Self::Stats(v) => v.emit(buffer),
57 Self::Config(v) => v.emit(buffer),
58 Self::Name(string) => {
59 buffer[..string.len()].copy_from_slice(string.as_bytes());
60 buffer[string.len()] = 0;
61 }
62 Self::GcInterval(value) => emit_u64(buffer, *value).unwrap(),
63 Self::Threshold1(value)
64 | Self::Threshold2(value)
65 | Self::Threshold3(value) => emit_u32(buffer, *value).unwrap(),
66 Self::Other(attr) => attr.emit_value(buffer),
67 }
68 }
69
70 fn kind(&self) -> u16 {
71 match self {
72 Self::Name(_) => NDTA_NAME,
73 Self::Config(_) => NDTA_CONFIG,
74 Self::Stats(_) => NDTA_STATS,
75 Self::Parms(_) => NDTA_PARMS,
76 Self::GcInterval(_) => NDTA_GC_INTERVAL,
77 Self::Threshold1(_) => NDTA_THRESH1,
78 Self::Threshold2(_) => NDTA_THRESH2,
79 Self::Threshold3(_) => NDTA_THRESH3,
80 Self::Other(attr) => attr.kind(),
81 }
82 }
83}
84
85impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
86 for NeighbourTableAttribute
87{
88 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
89 let payload = buf.value();
90 Ok(match buf.kind() {
91 NDTA_NAME => Self::Name(
92 parse_string(payload).context("invalid NDTA_NAME value")?,
93 ),
94 NDTA_CONFIG => Self::Config(
95 NeighbourTableConfig::parse(
96 &NeighbourTableConfigBuffer::new_checked(payload)
97 .context(format!("invalid NDTA_CONFIG {payload:?}"))?,
98 )
99 .context(format!("invalid NDTA_CONFIG {payload:?}"))?,
100 ),
101 NDTA_STATS => Self::Stats(
102 NeighbourTableStats::parse(
103 &NeighbourTableStatsBuffer::new_checked(payload)
104 .context(format!("invalid NDTA_STATS {payload:?}"))?,
105 )
106 .context(format!("invalid NDTA_STATS {payload:?}"))?,
107 ),
108 NDTA_PARMS => {
109 let err = |payload| format!("invalid NDTA_PARMS {payload:?}");
110 Self::Parms(
111 VecNeighbourTableParameter::parse(
112 &NlaBuffer::new_checked(payload)
113 .context(err(payload))?,
114 )
115 .context(err(payload))?
116 .0,
117 )
118 }
119 NDTA_GC_INTERVAL => Self::GcInterval(
120 parse_u64(payload).context("invalid NDTA_GC_INTERVAL value")?,
121 ),
122 NDTA_THRESH1 => Self::Threshold1(
123 parse_u32(payload).context("invalid NDTA_THRESH1 value")?,
124 ),
125 NDTA_THRESH2 => Self::Threshold2(
126 parse_u32(payload).context("invalid NDTA_THRESH2 value")?,
127 ),
128 NDTA_THRESH3 => Self::Threshold3(
129 parse_u32(payload).context("invalid NDTA_THRESH3 value")?,
130 ),
131 kind => Self::Other(
132 DefaultNla::parse(buf)
133 .context(format!("unknown NLA type {kind}"))?,
134 ),
135 })
136 }
137}