netlink_packet_route/tc/actions/
message.rs
1use anyhow::Context;
4use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer, NlasIterator};
5use netlink_packet_utils::{DecodeError, Emitable, Parseable};
6use std::convert::TryInto as _;
7
8use crate::tc::actions::{TcActionMessageBuffer, TcActionMessageHeader};
9use crate::tc::TcAction;
10
11#[derive(Debug, PartialEq, Eq, Clone, Default)]
15#[non_exhaustive]
16pub struct TcActionMessage {
17 pub header: TcActionMessageHeader,
19 pub attributes: Vec<TcActionMessageAttribute>,
21}
22
23const TCA_ACT_FLAG_LARGE_DUMP_ON: u32 = 1 << 0;
24const TCA_ACT_FLAG_TERSE_DUMP: u32 = 1 << 1;
25
26bitflags! {
27 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default, PartialOrd, Ord, Hash)]
29 #[non_exhaustive]
30 pub struct TcActionMessageFlags: u32 {
31 const LargeDump = TCA_ACT_FLAG_LARGE_DUMP_ON;
34 const TerseDump = TCA_ACT_FLAG_TERSE_DUMP;
37 const _ = !0;
38 }
39}
40
41#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, PartialOrd, Ord, Hash)]
48pub struct TcActionMessageFlagsWithSelector {
49 pub flags: TcActionMessageFlags,
52 pub selector: TcActionMessageFlags,
60}
61
62impl Nla for TcActionMessageFlagsWithSelector {
63 fn value_len(&self) -> usize {
64 8
65 }
66
67 fn kind(&self) -> u16 {
68 TCA_ROOT_FLAGS
69 }
70
71 fn emit_value(&self, buffer: &mut [u8]) {
72 buffer[..4].copy_from_slice(&self.flags.bits().to_ne_bytes());
73 buffer[4..8].copy_from_slice(&self.selector.bits().to_ne_bytes());
74 }
75}
76
77impl TcActionMessageFlagsWithSelector {
78 #[must_use]
86 pub fn new(flags: TcActionMessageFlags) -> Self {
87 Self { flags, selector: flags }
88 }
89
90 #[must_use]
96 pub fn new_with_selector(flags: TcActionMessageFlags, selector: TcActionMessageFlags) -> Self {
97 Self { flags, selector }
98 }
99}
100
101impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<NlaBuffer<&'a T>>
102 for TcActionMessageFlagsWithSelector
103{
104 type Error = DecodeError;
105 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
106 let value = buf.value();
107 if value.len() != 8 {
108 return Err(DecodeError::from("invalid length"));
109 }
110 let flags = TcActionMessageFlags::from_bits(u32::from_ne_bytes(
111 value[0..4].try_into().context("invalid length")?,
112 ))
113 .ok_or_else(|| DecodeError::from("invalid flags"))?;
114 let selector = TcActionMessageFlags::from_bits(u32::from_ne_bytes(
115 value[4..].try_into().context("invalid length")?,
116 ))
117 .ok_or_else(|| DecodeError::from("invalid flags selector"))?;
118 Ok(Self::new_with_selector(flags, selector))
119 }
120}
121
122const TCA_ACT_TAB: u16 = 1;
123const TCA_ROOT_FLAGS: u16 = 2;
124const TCA_ROOT_COUNT: u16 = 3;
125const TCA_ROOT_TIME_DELTA: u16 = 4;
126const TCA_ROOT_EXT_WARN_MSG: u16 = 5;
127
128#[derive(Debug, PartialEq, Eq, Clone)]
133#[non_exhaustive]
134pub enum TcActionMessageAttribute {
135 Actions(Vec<TcAction>),
137 Flags(TcActionMessageFlagsWithSelector),
139 RootCount(u32),
141 RootTimeDelta(u32),
143 RootExtWarnMsg(String),
145 Other(DefaultNla),
147}
148
149impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<NlaBuffer<&'a T>> for TcActionMessageAttribute {
150 type Error = DecodeError;
151 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
152 Ok(match buf.kind() {
153 TCA_ACT_TAB => {
154 let actions = NlasIterator::new(buf.value())
155 .map(|nla| TcAction::parse(&nla?))
156 .collect::<Result<Vec<_>, _>>()
157 .map_err(|err| DecodeError::Other(err.into()))?;
158 Self::Actions(actions)
159 }
160 TCA_ROOT_FLAGS => Self::Flags(TcActionMessageFlagsWithSelector::parse(buf)?),
161 TCA_ROOT_COUNT => {
162 let count = u32::from_ne_bytes(buf.value().try_into().context("invalid length")?);
163 Self::RootCount(count)
164 }
165 TCA_ROOT_TIME_DELTA => {
166 let delta = u32::from_be_bytes(buf.value().try_into().context("invalid length")?);
167 Self::RootTimeDelta(delta)
168 }
169 TCA_ROOT_EXT_WARN_MSG => {
170 let msg = String::from_utf8(buf.value().to_vec()).context("invalid utf8")?;
171 Self::RootExtWarnMsg(msg)
172 }
173 _ => Self::Other(DefaultNla::parse(buf)?),
174 })
175 }
176}
177
178impl Nla for TcActionMessageAttribute {
179 fn value_len(&self) -> usize {
180 match self {
181 Self::Actions(actions) => actions.as_slice().buffer_len(),
182 Self::Flags(_) => 8,
183 Self::RootCount(_) => 4,
184 Self::RootTimeDelta(_) => 4,
185 Self::RootExtWarnMsg(msg) => msg.len(),
186 Self::Other(nla) => nla.value_len(),
187 }
188 }
189
190 fn kind(&self) -> u16 {
191 match self {
192 Self::Actions(_) => TCA_ACT_TAB,
193 Self::Flags(_) => TCA_ROOT_FLAGS,
194 Self::RootCount(_) => TCA_ROOT_COUNT,
195 Self::RootTimeDelta(_) => TCA_ROOT_TIME_DELTA,
196 Self::RootExtWarnMsg(_) => TCA_ROOT_EXT_WARN_MSG,
197 Self::Other(nla) => nla.kind(),
198 }
199 }
200
201 fn emit_value(&self, buffer: &mut [u8]) {
202 match self {
203 Self::Actions(actions) => actions.as_slice().emit(buffer),
204 Self::Flags(flags) => {
205 flags.emit_value(buffer);
206 }
207 Self::RootCount(count) => {
208 buffer.copy_from_slice(&count.to_ne_bytes());
209 }
210 Self::RootTimeDelta(delta) => {
211 buffer.copy_from_slice(&delta.to_be_bytes());
212 }
213 Self::RootExtWarnMsg(msg) => buffer.copy_from_slice(msg.as_bytes()),
214 Self::Other(nla) => nla.emit_value(buffer),
215 }
216 }
217}
218
219impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<TcActionMessageBuffer<&'a T>> for TcActionMessage {
220 type Error = DecodeError;
221 fn parse(buf: &TcActionMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
222 let attrs: Result<Vec<_>, DecodeError> = buf
223 .attributes()
224 .map(|attr| TcActionMessageAttribute::parse(&attr?))
225 .collect::<Result<Vec<_>, _>>();
226
227 Ok(Self {
228 header: TcActionMessageHeader::parse(buf)
229 .context("failed to parse tc message header")?,
230 attributes: attrs?,
231 })
232 }
233}
234
235impl Emitable for TcActionMessage {
236 fn buffer_len(&self) -> usize {
237 self.header.buffer_len() + self.attributes.as_slice().buffer_len()
238 }
239
240 fn emit(&self, buffer: &mut [u8]) {
241 self.header.emit(buffer);
242 self.attributes.as_slice().emit(&mut buffer[self.header.buffer_len()..]);
243 }
244}