netlink_packet_route/tc/
message.rs

1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::{
4    DecodeError, Emitable, ErrorContext, Parseable, ParseableParametrized,
5};
6
7use super::{TcAttribute, TcHeader, TcMessageBuffer};
8
9#[derive(Debug, PartialEq, Eq, Clone, Default)]
10#[non_exhaustive]
11pub struct TcMessage {
12    pub header: TcHeader,
13    pub attributes: Vec<TcAttribute>,
14}
15
16impl TcMessage {
17    pub fn into_parts(self) -> (TcHeader, Vec<TcAttribute>) {
18        (self.header, self.attributes)
19    }
20
21    pub fn from_parts(header: TcHeader, attributes: Vec<TcAttribute>) -> Self {
22        TcMessage { header, attributes }
23    }
24
25    /// Create a new `TcMessage` with the given index
26    pub fn with_index(index: i32) -> Self {
27        Self {
28            header: TcHeader {
29                index,
30                ..Default::default()
31            },
32            attributes: Vec::new(),
33        }
34    }
35}
36
37impl<'a, T: AsRef<[u8]> + 'a> Parseable<TcMessageBuffer<&'a T>> for TcMessage {
38    fn parse(buf: &TcMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
39        Ok(Self {
40            header: TcHeader::parse(buf)
41                .context("failed to parse tc message header")?,
42            attributes: Vec::<TcAttribute>::parse(buf)
43                .context("failed to parse tc message NLAs")?,
44        })
45    }
46}
47
48impl<'a, T: AsRef<[u8]> + 'a> Parseable<TcMessageBuffer<&'a T>>
49    for Vec<TcAttribute>
50{
51    fn parse(buf: &TcMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
52        let mut attributes = vec![];
53        let mut kind = String::new();
54
55        for nla_buf in buf.attributes() {
56            let attribute =
57                TcAttribute::parse_with_param(&nla_buf?, kind.as_str())?;
58            if let TcAttribute::Kind(s) = &attribute {
59                kind = s.to_string();
60            }
61            attributes.push(attribute)
62        }
63        Ok(attributes)
64    }
65}
66
67impl Emitable for TcMessage {
68    fn buffer_len(&self) -> usize {
69        self.header.buffer_len() + self.attributes.as_slice().buffer_len()
70    }
71
72    fn emit(&self, buffer: &mut [u8]) {
73        self.header.emit(buffer);
74        self.attributes
75            .as_slice()
76            .emit(&mut buffer[self.header.buffer_len()..]);
77    }
78}