Skip to main content

netlink_packet_route/tc/filters/
cls_u32.rs

1// SPDX-License-Identifier: MIT
2
3use super::u32_flags::{TcU32OptionFlags, TcU32SelectorFlags};
4use crate::tc::{TcAction, TcError, TcHandle};
5/// U32 filter
6///
7/// In its simplest form the U32 filter is a list of records, each
8/// consisting of two fields: a selector and an action. The selectors,
9/// described below, are compared with the currently processed IP packet
10/// until the first match occurs, and then the associated action is
11/// performed.
12use 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    //pad: (u8, 3),
169    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        // Expect the buffer to be large enough to hold `nkeys`.
193        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            // unwrap: this never fails to parse.
239            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}