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