netlink_packet_route/tc/filters/
matchall.rs
1use crate::tc::{TcAction, TcError, TcHandle};
4use byteorder::{ByteOrder, NativeEndian};
8use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer, NlasIterator};
9use netlink_packet_utils::parsers::parse_u32;
10use netlink_packet_utils::traits::{Emitable, Parseable};
11
12const TCA_MATCHALL_CLASSID: u16 = 1;
13const TCA_MATCHALL_ACT: u16 = 2;
14const TCA_MATCHALL_FLAGS: u16 = 3;
15const TCA_MATCHALL_PCNT: u16 = 4;
16
17#[derive(Debug, PartialEq, Eq, Clone)]
18#[non_exhaustive]
19pub struct TcFilterMatchAll {}
20impl TcFilterMatchAll {
21 pub const KIND: &'static str = "matchall";
22}
23
24#[derive(Debug, PartialEq, Eq, Clone)]
25#[non_exhaustive]
26pub enum TcFilterMatchAllOption {
27 ClassId(TcHandle),
28 Action(Vec<TcAction>),
29 Pnct(Vec<u8>),
30 Flags(u32),
31 Other(DefaultNla),
32}
33
34impl Nla for TcFilterMatchAllOption {
35 fn value_len(&self) -> usize {
36 match self {
37 Self::Pnct(b) => b.len(),
38 Self::ClassId(_) => 4,
39 Self::Flags(_) => 4,
40 Self::Action(acts) => acts.as_slice().buffer_len(),
41 Self::Other(attr) => attr.value_len(),
42 }
43 }
44
45 fn emit_value(&self, buffer: &mut [u8]) {
46 match self {
47 Self::Pnct(b) => buffer.copy_from_slice(b.as_slice()),
48 Self::ClassId(i) => NativeEndian::write_u32(buffer, (*i).into()),
49 Self::Flags(i) => NativeEndian::write_u32(buffer, *i),
50 Self::Action(acts) => acts.as_slice().emit(buffer),
51 Self::Other(attr) => attr.emit_value(buffer),
52 }
53 }
54
55 fn kind(&self) -> u16 {
56 match self {
57 Self::ClassId(_) => TCA_MATCHALL_CLASSID,
58 Self::Action(_) => TCA_MATCHALL_ACT,
59 Self::Pnct(_) => TCA_MATCHALL_PCNT,
60 Self::Flags(_) => TCA_MATCHALL_FLAGS,
61 Self::Other(attr) => attr.kind(),
62 }
63 }
64}
65
66impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for TcFilterMatchAllOption {
67 type Error = TcError;
68 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, TcError> {
69 let payload = buf.value();
70 Ok(match buf.kind() {
71 TCA_MATCHALL_CLASSID => Self::ClassId(
72 parse_u32(payload)
73 .map_err(|error| TcError::ParseFilterMatchallOption {
74 kind: "TCA_MATCHALL_UNSPEC",
75 error,
76 })?
77 .into(),
78 ),
79 TCA_MATCHALL_ACT => {
80 let mut acts = vec![];
81 for act in NlasIterator::new(payload) {
82 let act = act?;
83 acts.push(TcAction::parse(&act)?);
84 }
85 Self::Action(acts)
86 }
87 TCA_MATCHALL_PCNT => Self::Pnct(payload.to_vec()),
88 TCA_MATCHALL_FLAGS => Self::Flags(parse_u32(payload).map_err(|error| {
89 TcError::ParseFilterMatchallOption { kind: "TCA_MATCHALL_FLAGS", error }
90 })?),
91 kind => Self::Other(DefaultNla::parse(buf).map_err(|error| {
92 TcError::UnknownFilterMatchAllOption { kind: kind.to_string(), error }
93 })?),
94 })
95 }
96}