netlink_packet_route/tc/actions/
message.rs1use anyhow::Context;
4use netlink_packet_utils::nla::{DefaultNla, NlaBuffer};
5use netlink_packet_utils::nla::{Nla, NlasIterator};
6use netlink_packet_utils::{DecodeError, Emitable, Parseable};
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 {
88 flags,
89 selector: flags,
90 }
91 }
92
93 #[must_use]
99 pub fn new_with_selector(
100 flags: TcActionMessageFlags,
101 selector: TcActionMessageFlags,
102 ) -> Self {
103 Self { flags, selector }
104 }
105}
106
107impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<NlaBuffer<&'a T>>
108 for TcActionMessageFlagsWithSelector
109{
110 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
111 let value = buf.value();
112 if value.len() != 8 {
113 return Err(DecodeError::from("invalid length"));
114 }
115 let flags = TcActionMessageFlags::from_bits(u32::from_ne_bytes(
116 value[0..4].try_into().context("invalid length")?,
117 ))
118 .ok_or_else(|| DecodeError::from("invalid flags"))?;
119 let selector = TcActionMessageFlags::from_bits(u32::from_ne_bytes(
120 value[4..].try_into().context("invalid length")?,
121 ))
122 .ok_or_else(|| DecodeError::from("invalid flags selector"))?;
123 Ok(Self::new_with_selector(flags, selector))
124 }
125}
126
127const TCA_ACT_TAB: u16 = 1;
128const TCA_ROOT_FLAGS: u16 = 2;
129const TCA_ROOT_COUNT: u16 = 3;
130const TCA_ROOT_TIME_DELTA: u16 = 4;
131const TCA_ROOT_EXT_WARN_MSG: u16 = 5;
132
133#[derive(Debug, PartialEq, Eq, Clone)]
138#[non_exhaustive]
139pub enum TcActionMessageAttribute {
140 Actions(Vec<TcAction>),
142 Flags(TcActionMessageFlagsWithSelector),
144 RootCount(u32),
146 RootTimeDelta(u32),
148 RootExtWarnMsg(String),
150 Other(DefaultNla),
152}
153
154impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<NlaBuffer<&'a T>>
155 for TcActionMessageAttribute
156{
157 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
158 Ok(match buf.kind() {
159 TCA_ACT_TAB => {
160 let actions = NlasIterator::new(buf.value())
161 .map(|nla| TcAction::parse(&nla?))
162 .collect::<Result<Vec<_>, _>>()?;
163 Self::Actions(actions)
164 }
165 TCA_ROOT_FLAGS => {
166 Self::Flags(TcActionMessageFlagsWithSelector::parse(buf)?)
167 }
168 TCA_ROOT_COUNT => {
169 let count = u32::from_ne_bytes(
170 buf.value().try_into().context("invalid length")?,
171 );
172 Self::RootCount(count)
173 }
174 TCA_ROOT_TIME_DELTA => {
175 let delta = u32::from_be_bytes(
176 buf.value().try_into().context("invalid length")?,
177 );
178 Self::RootTimeDelta(delta)
179 }
180 TCA_ROOT_EXT_WARN_MSG => {
181 let msg = String::from_utf8(buf.value().to_vec())
182 .context("invalid utf8")?;
183 Self::RootExtWarnMsg(msg)
184 }
185 _ => Self::Other(DefaultNla::parse(buf)?),
186 })
187 }
188}
189
190impl Nla for TcActionMessageAttribute {
191 fn value_len(&self) -> usize {
192 match self {
193 Self::Actions(actions) => actions.as_slice().buffer_len(),
194 Self::Flags(_) => 8,
195 Self::RootCount(_) => 4,
196 Self::RootTimeDelta(_) => 4,
197 Self::RootExtWarnMsg(msg) => msg.len(),
198 Self::Other(nla) => nla.value_len(),
199 }
200 }
201
202 fn kind(&self) -> u16 {
203 match self {
204 Self::Actions(_) => TCA_ACT_TAB,
205 Self::Flags(_) => TCA_ROOT_FLAGS,
206 Self::RootCount(_) => TCA_ROOT_COUNT,
207 Self::RootTimeDelta(_) => TCA_ROOT_TIME_DELTA,
208 Self::RootExtWarnMsg(_) => TCA_ROOT_EXT_WARN_MSG,
209 Self::Other(nla) => nla.kind(),
210 }
211 }
212
213 fn emit_value(&self, buffer: &mut [u8]) {
214 match self {
215 Self::Actions(actions) => actions.as_slice().emit(buffer),
216 Self::Flags(flags) => {
217 flags.emit_value(buffer);
218 }
219 Self::RootCount(count) => {
220 buffer.copy_from_slice(&count.to_ne_bytes());
221 }
222 Self::RootTimeDelta(delta) => {
223 buffer.copy_from_slice(&delta.to_be_bytes());
224 }
225 Self::RootExtWarnMsg(msg) => buffer.copy_from_slice(msg.as_bytes()),
226 Self::Other(nla) => nla.emit_value(buffer),
227 }
228 }
229}
230
231impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<TcActionMessageBuffer<&'a T>>
232 for TcActionMessage
233{
234 fn parse(buf: &TcActionMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
235 let attrs: Result<Vec<_>, DecodeError> = buf
236 .attributes()
237 .map(|attr| TcActionMessageAttribute::parse(&attr?))
238 .collect::<Result<Vec<_>, _>>();
239
240 Ok(Self {
241 header: TcActionMessageHeader::parse(buf)
242 .context("failed to parse tc message header")?,
243 attributes: attrs?,
244 })
245 }
246}
247
248impl Emitable for TcActionMessage {
249 fn buffer_len(&self) -> usize {
250 self.header.buffer_len() + self.attributes.as_slice().buffer_len()
251 }
252
253 fn emit(&self, buffer: &mut [u8]) {
254 self.header.emit(buffer);
255 self.attributes
256 .as_slice()
257 .emit(&mut buffer[self.header.buffer_len()..]);
258 }
259}