netlink_packet_route/tc/filters/
cls_u32.rs1use super::u32_flags::{TcU32OptionFlags, TcU32SelectorFlags};
4use crate::tc::{TcAction, TcError, TcHandle};
5use byteorder::{ByteOrder, NativeEndian};
13use netlink_packet_utils::DecodeError;
14use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer, NlasIterator};
15use netlink_packet_utils::parsers::parse_u32;
16use netlink_packet_utils::traits::{Emitable, Parseable};
17
18const TC_U32_SEL_BUF_LEN: usize = 16;
19const TC_U32_KEY_BUF_LEN: usize = 16;
20
21const TCA_U32_CLASSID: u16 = 1;
22const TCA_U32_HASH: u16 = 2;
23const TCA_U32_LINK: u16 = 3;
24const TCA_U32_DIVISOR: u16 = 4;
25const TCA_U32_SEL: u16 = 5;
26const TCA_U32_POLICE: u16 = 6;
27const TCA_U32_ACT: u16 = 7;
28const TCA_U32_INDEV: u16 = 8;
29const TCA_U32_PCNT: u16 = 9;
30const TCA_U32_MARK: u16 = 10;
31const TCA_U32_FLAGS: u16 = 11;
32
33#[derive(Debug, PartialEq, Eq, Clone)]
34#[non_exhaustive]
35pub struct TcFilterU32 {}
36
37impl TcFilterU32 {
38 pub const KIND: &'static str = "u32";
39}
40
41#[derive(Debug, PartialEq, Eq, Clone)]
42#[non_exhaustive]
43pub enum TcFilterU32Option {
44 ClassId(TcHandle),
45 Hash(u32),
46 Link(u32),
47 Divisor(u32),
48 Selector(TcU32Selector),
49 Police(Vec<u8>),
50 Action(Vec<TcAction>),
51 Indev(Vec<u8>),
52 Pnct(Vec<u8>),
53 Mark(Vec<u8>),
54 Flags(TcU32OptionFlags),
55 Other(DefaultNla),
56}
57
58impl Nla for TcFilterU32Option {
59 fn value_len(&self) -> usize {
60 match self {
61 Self::Police(b) | Self::Indev(b) | Self::Pnct(b) | Self::Mark(b) => b.len(),
62 Self::Hash(_) | Self::Link(_) | Self::Divisor(_) | Self::Flags(_) => 4,
63 Self::ClassId(_) => 4,
64 Self::Selector(s) => s.buffer_len(),
65 Self::Action(acts) => acts.as_slice().buffer_len(),
66 Self::Other(attr) => attr.value_len(),
67 }
68 }
69
70 fn emit_value(&self, buffer: &mut [u8]) {
71 match self {
72 Self::Police(b) | Self::Indev(b) | Self::Pnct(b) | Self::Mark(b) => {
73 buffer.copy_from_slice(b.as_slice())
74 }
75 Self::Hash(i) | Self::Link(i) | Self::Divisor(i) => NativeEndian::write_u32(buffer, *i),
76 Self::Flags(f) => NativeEndian::write_u32(buffer, f.bits()),
77 Self::ClassId(i) => NativeEndian::write_u32(buffer, (*i).into()),
78 Self::Selector(s) => s.emit(buffer),
79 Self::Action(acts) => acts.as_slice().emit(buffer),
80 Self::Other(attr) => attr.emit_value(buffer),
81 }
82 }
83
84 fn kind(&self) -> u16 {
85 match self {
86 Self::ClassId(_) => TCA_U32_CLASSID,
87 Self::Hash(_) => TCA_U32_HASH,
88 Self::Link(_) => TCA_U32_LINK,
89 Self::Divisor(_) => TCA_U32_DIVISOR,
90 Self::Selector(_) => TCA_U32_SEL,
91 Self::Police(_) => TCA_U32_POLICE,
92 Self::Action(_) => TCA_U32_ACT,
93 Self::Indev(_) => TCA_U32_INDEV,
94 Self::Pnct(_) => TCA_U32_PCNT,
95 Self::Mark(_) => TCA_U32_MARK,
96 Self::Flags(_) => TCA_U32_FLAGS,
97 Self::Other(attr) => attr.kind(),
98 }
99 }
100}
101
102impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for TcFilterU32Option {
103 type Error = TcError;
104 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, TcError> {
105 let payload = buf.value();
106 Ok(match buf.kind() {
107 TCA_U32_CLASSID => Self::ClassId(TcHandle::from(
108 parse_u32(payload)
109 .map_err(|error| TcError::InvalidValue { kind: "TCA_U32_UNSPEC", error })?,
110 )),
111 TCA_U32_HASH => Self::Hash(
112 parse_u32(payload)
113 .map_err(|error| TcError::InvalidValue { kind: "TCA_U32_HASH", error })?,
114 ),
115 TCA_U32_LINK => Self::Link(
116 parse_u32(payload)
117 .map_err(|error| TcError::InvalidValue { kind: "TCA_U32_LINK", error })?,
118 ),
119 TCA_U32_DIVISOR => Self::Divisor(
120 parse_u32(payload)
121 .map_err(|error| TcError::InvalidValue { kind: "TCA_U32_DIVISOR", error })?,
122 ),
123 TCA_U32_SEL => Self::Selector(TcU32Selector::parse(
124 &TcU32SelectorBuffer::new(payload)
125 .map_err(|error| TcError::InvalidValue { kind: "TCA_U32_SEL", error })?,
126 )?),
127 TCA_U32_POLICE => Self::Police(payload.to_vec()),
128 TCA_U32_ACT => {
129 let mut acts = vec![];
130 for act in NlasIterator::new(payload) {
131 let act = act?;
132 acts.push(TcAction::parse(&act)?);
133 }
134 Self::Action(acts)
135 }
136 TCA_U32_INDEV => Self::Indev(payload.to_vec()),
137 TCA_U32_PCNT => Self::Pnct(payload.to_vec()),
138 TCA_U32_MARK => Self::Mark(payload.to_vec()),
139 TCA_U32_FLAGS => Self::Flags(TcU32OptionFlags::from_bits_retain(
140 parse_u32(payload)
141 .map_err(|error| TcError::InvalidValue { kind: "TCA_U32_FLAGS", error })?,
142 )),
143 kind => Self::Other(
144 DefaultNla::parse(buf).map_err(|error| TcError::UnknownNla { kind, error })?,
145 ),
146 })
147 }
148}
149
150#[derive(Debug, PartialEq, Eq, Clone, Default)]
151#[non_exhaustive]
152pub struct TcU32Selector {
153 pub flags: TcU32SelectorFlags,
154 pub offshift: u8,
155 pub nkeys: u8,
156 pub offmask: u16,
157 pub off: u16,
158 pub offoff: u16,
159 pub hoff: u16,
160 pub hmask: u32,
161 pub keys: Vec<TcU32Key>,
162}
163
164buffer!(TcU32SelectorBuffer() {
165 flags: (u8, 0),
166 offshift: (u8, 1),
167 nkeys: (u8, 2),
168 offmask: (u16, 4..6),
170 off: (u16, 6..8),
171 offoff: (u16, 8..10),
172 hoff: (u16, 10..12),
173 hmask: (u32, 12..TC_U32_SEL_BUF_LEN),
174 keys: (slice, TC_U32_SEL_BUF_LEN..),
175});
176
177impl<T: AsRef<[u8]>> TcU32SelectorBuffer<T> {
178 pub fn new(buffer: T) -> Result<Self, DecodeError> {
179 let packet = Self::new_unchecked(buffer);
180 packet.check_buffer_length()?;
181 Ok(packet)
182 }
183
184 fn check_buffer_length(&self) -> Result<(), DecodeError> {
185 let len = self.buffer.as_ref().len();
186 if len < TC_U32_SEL_BUF_LEN {
187 return Err(format!(
188 "invalid TcU32SelectorBuffer: length {len} < {TC_U32_SEL_BUF_LEN}"
189 )
190 .into());
191 }
192 let expected_len = ((self.nkeys() as usize) * TC_U32_KEY_BUF_LEN) + TC_U32_SEL_BUF_LEN;
194 if len < expected_len {
195 return Err(
196 format!("invalid RouteNextHopBuffer: length {} < {}", len, expected_len,).into()
197 );
198 }
199 Ok(())
200 }
201}
202
203impl Emitable for TcU32Selector {
204 fn buffer_len(&self) -> usize {
205 TC_U32_SEL_BUF_LEN + (self.nkeys as usize * TC_U32_KEY_BUF_LEN)
206 }
207
208 fn emit(&self, buffer: &mut [u8]) {
209 let mut packet = TcU32SelectorBuffer::new_unchecked(buffer);
210 packet.set_flags(self.flags.bits());
211 packet.set_offshift(self.offshift);
212 packet.set_offmask(self.offmask);
213 packet.set_off(self.off);
214 packet.set_offoff(self.offoff);
215 packet.set_hoff(self.hoff);
216 packet.set_hmask(self.hmask);
217 packet.set_nkeys(self.nkeys);
218
219 let key_buf = packet.keys_mut();
220 for (i, k) in self.keys.iter().enumerate() {
221 k.emit(&mut key_buf[(i * TC_U32_KEY_BUF_LEN)..((i + 1) * TC_U32_KEY_BUF_LEN)]);
222 }
223 }
224}
225
226impl<T: AsRef<[u8]> + ?Sized> Parseable<TcU32SelectorBuffer<&T>> for TcU32Selector {
227 type Error = TcError;
228 fn parse(buf: &TcU32SelectorBuffer<&T>) -> Result<Self, TcError> {
229 let nkeys = buf.nkeys();
230 let mut keys = Vec::<TcU32Key>::with_capacity(nkeys.into());
231 let key_payload = buf.keys();
232 for i in 0..nkeys {
233 let i = i as usize;
234 let keybuf = TcU32KeyBuffer::new(
235 &key_payload[(i * TC_U32_KEY_BUF_LEN)..(i + 1) * TC_U32_KEY_BUF_LEN],
236 )
237 .map_err(|error| TcError::InvalidU32Key(error))?;
238 keys.push(TcU32Key::parse(&keybuf).unwrap());
240 }
241
242 Ok(Self {
243 flags: TcU32SelectorFlags::from_bits_retain(buf.flags()),
244 offshift: buf.offshift(),
245 nkeys,
246 offmask: buf.offmask(),
247 off: buf.off(),
248 offoff: buf.offoff(),
249 hoff: buf.hoff(),
250 hmask: buf.hmask(),
251 keys,
252 })
253 }
254}
255
256#[derive(Debug, PartialEq, Eq, Clone, Default)]
257#[non_exhaustive]
258pub struct TcU32Key {
259 pub mask: u32,
260 pub val: u32,
261 pub off: i32,
262 pub offmask: i32,
263}
264
265buffer!(TcU32KeyBuffer(TC_U32_KEY_BUF_LEN) {
266 mask: (u32, 0..4),
267 val: (u32, 4..8),
268 off: (i32, 8..12),
269 offmask: (i32, 12..TC_U32_KEY_BUF_LEN),
270});
271
272impl Emitable for TcU32Key {
273 fn buffer_len(&self) -> usize {
274 TC_U32_KEY_BUF_LEN
275 }
276 fn emit(&self, buffer: &mut [u8]) {
277 let mut packet = TcU32KeyBuffer::new_unchecked(buffer);
278 packet.set_mask(self.mask);
279 packet.set_val(self.val);
280 packet.set_off(self.off);
281 packet.set_offmask(self.offmask);
282 }
283}
284
285impl<T: AsRef<[u8]>> Parseable<TcU32KeyBuffer<T>> for TcU32Key {
286 type Error = ();
287 fn parse(buf: &TcU32KeyBuffer<T>) -> Result<Self, ()> {
288 Ok(Self { mask: buf.mask(), val: buf.val(), off: buf.off(), offmask: buf.offmask() })
289 }
290}