Skip to main content

netlink_packet_route/tc/
message.rs

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