netlink_packet_route/tc/
options.rs
1use super::{
4 TcError, TcFilterMatchAll, TcFilterMatchAllOption, TcFilterU32, TcFilterU32Option,
5 TcQdiscFqCodel, TcQdiscFqCodelOption, TcQdiscIngress, TcQdiscIngressOption,
6};
7use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer, NlasIterator};
8use netlink_packet_utils::traits::{Parseable, ParseableParametrized};
9
10#[derive(Debug, PartialEq, Eq, Clone)]
11#[non_exhaustive]
12pub enum TcOption {
13 FqCodel(TcQdiscFqCodelOption),
14 Ingress(TcQdiscIngressOption),
16 U32(TcFilterU32Option),
18 MatchAll(TcFilterMatchAllOption),
20 Other(DefaultNla),
22}
23
24impl Nla for TcOption {
25 fn value_len(&self) -> usize {
26 match self {
27 Self::FqCodel(u) => u.value_len(),
28 Self::Ingress(u) => u.value_len(),
29 Self::U32(u) => u.value_len(),
30 Self::MatchAll(m) => m.value_len(),
31 Self::Other(o) => o.value_len(),
32 }
33 }
34
35 fn emit_value(&self, buffer: &mut [u8]) {
36 match self {
37 Self::FqCodel(u) => u.emit_value(buffer),
38 Self::Ingress(u) => u.emit_value(buffer),
39 Self::U32(u) => u.emit_value(buffer),
40 Self::MatchAll(m) => m.emit_value(buffer),
41 Self::Other(o) => o.emit_value(buffer),
42 }
43 }
44
45 fn kind(&self) -> u16 {
46 match self {
47 Self::FqCodel(u) => u.kind(),
48 Self::Ingress(u) => u.kind(),
49 Self::U32(u) => u.kind(),
50 Self::MatchAll(m) => m.kind(),
51 Self::Other(o) => o.kind(),
52 }
53 }
54}
55
56impl<'a, T> ParseableParametrized<NlaBuffer<&'a T>, &str> for TcOption
57where
58 T: AsRef<[u8]> + ?Sized,
59{
60 type Error = TcError;
61 fn parse_with_param(buf: &NlaBuffer<&'a T>, kind: &str) -> Result<Self, TcError> {
62 Ok(match kind {
63 TcQdiscIngress::KIND => {
64 Self::Ingress(TcQdiscIngressOption::parse(buf).map_err(|error| {
65 TcError::ParseTcaOptionAttributes { kind: "ingress", error }
66 })?)
67 }
68 TcQdiscFqCodel::KIND => Self::FqCodel(TcQdiscFqCodelOption::parse(buf)?),
69 TcFilterU32::KIND => Self::U32(TcFilterU32Option::parse(buf)?),
70 TcFilterMatchAll::KIND => Self::MatchAll(TcFilterMatchAllOption::parse(buf)?),
71 kind => Self::Other(
72 DefaultNla::parse(buf)
73 .map_err(|error| TcError::UnknownOption { kind: kind.to_string(), error })?,
74 ),
75 })
76 }
77}
78
79pub(crate) struct VecTcOption(pub(crate) Vec<TcOption>);
80
81impl<'a, T> ParseableParametrized<NlaBuffer<&'a T>, &str> for VecTcOption
82where
83 T: AsRef<[u8]> + ?Sized,
84{
85 type Error = TcError;
86 fn parse_with_param(buf: &NlaBuffer<&'a T>, kind: &str) -> Result<VecTcOption, TcError> {
87 Ok(match kind {
88 TcFilterU32::KIND
89 | TcFilterMatchAll::KIND
90 | TcQdiscIngress::KIND
91 | TcQdiscFqCodel::KIND => {
92 let mut nlas = vec![];
93 for nla in NlasIterator::new(buf.value()) {
94 let nla = nla?;
95 nlas.push(TcOption::parse_with_param(&nla, kind)?)
96 }
97 Self(nlas)
98 }
99 kind => Self(vec![TcOption::Other(
104 DefaultNla::parse(buf)
105 .map_err(|error| TcError::UnknownOption { kind: kind.to_string(), error })?,
106 )]),
107 })
108 }
109}