netlink_packet_route/tc/
message.rs

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