netlink_packet_route/tc/actions/
message.rs1use netlink_packet_core::{
4 parse_string, parse_u32, parse_u32_be, DecodeError, DefaultNla, Emitable,
5 ErrorContext, Nla, NlaBuffer, NlasIterator, Parseable,
6};
7
8use crate::tc::{
9 actions::{TcActionMessageBuffer, TcActionMessageHeader},
10 TcAction,
11};
12
13#[derive(Debug, PartialEq, Eq, Clone, Default)]
17#[non_exhaustive]
18pub struct TcActionMessage {
19 pub header: TcActionMessageHeader,
21 pub attributes: Vec<TcActionMessageAttribute>,
23}
24
25const TCA_ACT_FLAG_LARGE_DUMP_ON: u32 = 1 << 0;
26const TCA_ACT_FLAG_TERSE_DUMP: u32 = 1 << 1;
27
28bitflags! {
29 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default, PartialOrd, Ord, Hash)]
31 #[non_exhaustive]
32 pub struct TcActionMessageFlags: u32 {
33 const LargeDump = TCA_ACT_FLAG_LARGE_DUMP_ON;
36 const TerseDump = TCA_ACT_FLAG_TERSE_DUMP;
39 const _ = !0;
40 }
41}
42
43#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, PartialOrd, Ord, Hash)]
50pub struct TcActionMessageFlagsWithSelector {
51 pub flags: TcActionMessageFlags,
54 pub selector: TcActionMessageFlags,
62}
63
64impl Nla for TcActionMessageFlagsWithSelector {
65 fn value_len(&self) -> usize {
66 8
67 }
68
69 fn kind(&self) -> u16 {
70 TCA_ROOT_FLAGS
71 }
72
73 fn emit_value(&self, buffer: &mut [u8]) {
74 buffer[..4].copy_from_slice(&self.flags.bits().to_ne_bytes());
75 buffer[4..8].copy_from_slice(&self.selector.bits().to_ne_bytes());
76 }
77}
78
79impl TcActionMessageFlagsWithSelector {
80 #[must_use]
88 pub fn new(flags: TcActionMessageFlags) -> Self {
89 Self {
90 flags,
91 selector: flags,
92 }
93 }
94
95 #[must_use]
101 pub fn new_with_selector(
102 flags: TcActionMessageFlags,
103 selector: TcActionMessageFlags,
104 ) -> Self {
105 Self { flags, selector }
106 }
107}
108
109impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<NlaBuffer<&'a T>>
110 for TcActionMessageFlagsWithSelector
111{
112 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
113 let value = buf.value();
114 if value.len() != 8 {
115 return Err(DecodeError::from("invalid length"));
116 }
117 let flags = TcActionMessageFlags::from_bits(
118 parse_u32(&value[..4]).context("invalid flags")?,
119 )
120 .ok_or_else(|| DecodeError::from("invalid flags selector"))?;
121 let selector = TcActionMessageFlags::from_bits(
122 parse_u32(&value[4..]).context("invalid flags seclector")?,
123 )
124 .ok_or_else(|| DecodeError::from("invalid flags selector"))?;
125 Ok(Self::new_with_selector(flags, selector))
126 }
127}
128
129const TCA_ACT_TAB: u16 = 1;
130const TCA_ROOT_FLAGS: u16 = 2;
131const TCA_ROOT_COUNT: u16 = 3;
132const TCA_ROOT_TIME_DELTA: u16 = 4;
133const TCA_ROOT_EXT_WARN_MSG: u16 = 5;
134
135#[derive(Debug, PartialEq, Eq, Clone)]
140#[non_exhaustive]
141pub enum TcActionMessageAttribute {
142 Actions(Vec<TcAction>),
144 Flags(TcActionMessageFlagsWithSelector),
146 RootCount(u32),
148 RootTimeDelta(u32),
150 RootExtWarnMsg(String),
152 Other(DefaultNla),
154}
155
156impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<NlaBuffer<&'a T>>
157 for TcActionMessageAttribute
158{
159 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
160 Ok(match buf.kind() {
161 TCA_ACT_TAB => {
162 let actions = NlasIterator::new(buf.value())
163 .map(|nla| TcAction::parse(&nla?))
164 .collect::<Result<Vec<_>, _>>()?;
165 Self::Actions(actions)
166 }
167 TCA_ROOT_FLAGS => {
168 Self::Flags(TcActionMessageFlagsWithSelector::parse(buf)?)
169 }
170 TCA_ROOT_COUNT => {
171 let count =
172 parse_u32(buf.value()).context("Invalid TCA_ROOT_COUNT")?;
173 Self::RootCount(count)
174 }
175 TCA_ROOT_TIME_DELTA => {
176 let delta = parse_u32_be(buf.value())
177 .context("Invalid TCA_ROOT_TIME_DELTA")?;
178 Self::RootTimeDelta(delta)
179 }
180 TCA_ROOT_EXT_WARN_MSG => {
181 let msg = parse_string(buf.value())
182 .context("Invalid TCA_ROOT_EXT_WARN_MSG")?;
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}