netlink_packet_route/rtnl/tc/nlas/
mod.rs

1// SPDX-License-Identifier: MIT
2
3mod stats;
4pub use self::stats::*;
5
6mod stats_queue;
7pub use self::stats_queue::*;
8
9mod stats_basic;
10pub use self::stats_basic::*;
11
12mod options;
13pub use self::options::*;
14
15mod qdisc;
16pub use self::qdisc::*;
17
18mod filter;
19pub use self::filter::*;
20
21mod action;
22pub use self::action::*;
23
24#[cfg(test)]
25mod test;
26
27use crate::{
28    constants::*,
29    nlas::{self, DefaultNla, NlaBuffer},
30    traits::{Emitable, Parseable},
31    DecodeError,
32};
33
34#[derive(Debug, PartialEq, Eq, Clone)]
35pub enum Nla {
36    /// Unspecified
37    Unspec(Vec<u8>),
38    /// Name of queueing discipline
39    Kind(String),
40    /// Options follow
41    Options(Vec<TcOpt>),
42    /// Statistics
43    Stats(Stats),
44    /// Module-specific statistics
45    XStats(Vec<u8>),
46    /// Rate limit
47    Rate(Vec<u8>),
48    Fcnt(Vec<u8>),
49    Stats2(Vec<Stats2>),
50    Stab(Vec<u8>),
51    Chain(Vec<u8>),
52    HwOffload(u8),
53    Other(DefaultNla),
54}
55
56impl nlas::Nla for Nla {
57    #[rustfmt::skip]
58    fn value_len(&self) -> usize {
59        use self::Nla::*;
60        match *self {
61            // Vec<u8>
62            Unspec(ref bytes) | XStats(ref bytes) | Rate(ref bytes) | Fcnt(ref bytes)
63            | Stab(ref bytes) | Chain(ref bytes) => bytes.len(),
64            HwOffload(_) => 1,
65            Stats2(ref thing) => thing.as_slice().buffer_len(),
66            Stats(_) => STATS_LEN,
67            Kind(ref string) => string.as_bytes().len() + 1,
68            Options(ref opt) => opt.as_slice().buffer_len(),
69            // Defaults
70            Other(ref attr) => attr.value_len(),
71        }
72    }
73
74    #[cfg_attr(nightly, rustfmt::skip)]
75    fn emit_value(&self, buffer: &mut [u8]) {
76        use self::Nla::*;
77        match *self {
78            // Vec<u8>
79            Unspec(ref bytes)
80                | XStats(ref bytes)
81                | Rate(ref bytes)
82                | Fcnt(ref bytes)
83                | Stab(ref bytes)
84                | Chain(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),
85
86            HwOffload(ref val) => buffer[0] = *val,
87            Stats2(ref stats) => stats.as_slice().emit(buffer),
88            Stats(ref stats) => stats.emit(buffer),
89
90            Kind(ref string) => {
91                buffer[..string.as_bytes().len()].copy_from_slice(string.as_bytes());
92                buffer[string.as_bytes().len()] = 0;
93            }
94            Options(ref opt) => opt.as_slice().emit(buffer),
95
96            // Default
97            Other(ref attr) => attr.emit_value(buffer),
98        }
99    }
100
101    fn kind(&self) -> u16 {
102        use self::Nla::*;
103        match *self {
104            Unspec(_) => TCA_UNSPEC,
105            Kind(_) => TCA_KIND,
106            Options(_) => TCA_OPTIONS,
107            Stats(_) => TCA_STATS,
108            XStats(_) => TCA_XSTATS,
109            Rate(_) => TCA_RATE,
110            Fcnt(_) => TCA_FCNT,
111            Stats2(_) => TCA_STATS2,
112            Stab(_) => TCA_STAB,
113            Chain(_) => TCA_CHAIN,
114            HwOffload(_) => TCA_HW_OFFLOAD,
115            Other(ref nla) => nla.kind(),
116        }
117    }
118}
119
120#[derive(Debug, PartialEq, Eq, Clone)]
121pub enum Stats2 {
122    StatsApp(Vec<u8>),
123    StatsBasic(Vec<u8>),
124    StatsQueue(Vec<u8>),
125    Other(DefaultNla),
126}
127
128impl nlas::Nla for Stats2 {
129    fn value_len(&self) -> usize {
130        use self::Stats2::*;
131        match *self {
132            StatsBasic(ref bytes) | StatsQueue(ref bytes) | StatsApp(ref bytes) => bytes.len(),
133            Other(ref nla) => nla.value_len(),
134        }
135    }
136
137    fn emit_value(&self, buffer: &mut [u8]) {
138        use self::Stats2::*;
139        match *self {
140            StatsBasic(ref bytes) | StatsQueue(ref bytes) | StatsApp(ref bytes) => {
141                buffer.copy_from_slice(bytes.as_slice())
142            }
143            Other(ref nla) => nla.emit_value(buffer),
144        }
145    }
146
147    fn kind(&self) -> u16 {
148        use self::Stats2::*;
149        match *self {
150            StatsApp(_) => TCA_STATS_APP,
151            StatsBasic(_) => TCA_STATS_BASIC,
152            StatsQueue(_) => TCA_STATS_QUEUE,
153            Other(ref nla) => nla.kind(),
154        }
155    }
156}
157
158impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Stats2 {
159    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
160        let payload = buf.value();
161        Ok(match buf.kind() {
162            TCA_STATS_APP => Self::StatsApp(payload.to_vec()),
163            TCA_STATS_BASIC => Self::StatsBasic(payload.to_vec()),
164            TCA_STATS_QUEUE => Self::StatsQueue(payload.to_vec()),
165            _ => Self::Other(DefaultNla::parse(buf)?),
166        })
167    }
168}