netlink_packet_route/tc/
header.rs

1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::{
4    DecodeError, Emitable, NlaBuffer, NlasIterator, Parseable,
5};
6
7use crate::AddressFamily;
8
9const TC_HEADER_LEN: usize = 20;
10
11buffer!(TcMessageBuffer(TC_HEADER_LEN) {
12    family: (u8, 0),
13    pad1: (u8, 1),
14    pad2: (u16, 2..4),
15    index: (i32, 4..8),
16    handle: (u32, 8..12),
17    parent: (u32, 12..16),
18    info: (u32, 16..TC_HEADER_LEN),
19    payload: (slice, TC_HEADER_LEN..),
20});
21
22impl<'a, T: AsRef<[u8]> + ?Sized> TcMessageBuffer<&'a T> {
23    pub fn attributes(
24        &self,
25    ) -> impl Iterator<Item = Result<NlaBuffer<&'a [u8]>, DecodeError>> {
26        NlasIterator::new(self.payload())
27    }
28}
29
30#[derive(Debug, PartialEq, Eq, Clone, Default)]
31pub struct TcHeader {
32    pub family: AddressFamily,
33    // Interface index
34    pub index: i32,
35    // Qdisc handle
36    pub handle: TcHandle,
37    // Parent Qdisc
38    pub parent: TcHandle,
39    pub info: u32,
40}
41
42impl TcHeader {
43    pub const TCM_IFINDEX_MAGIC_BLOCK: u32 = 0xFFFFFFFF;
44}
45
46impl Emitable for TcHeader {
47    fn buffer_len(&self) -> usize {
48        TC_HEADER_LEN
49    }
50
51    fn emit(&self, buffer: &mut [u8]) {
52        let mut packet = TcMessageBuffer::new(buffer);
53        packet.set_family(self.family.into());
54        packet.set_index(self.index);
55        packet.set_handle(self.handle.into());
56        packet.set_parent(self.parent.into());
57        packet.set_info(self.info);
58    }
59}
60
61impl<T: AsRef<[u8]>> Parseable<TcMessageBuffer<T>> for TcHeader {
62    fn parse(buf: &TcMessageBuffer<T>) -> Result<Self, DecodeError> {
63        Ok(Self {
64            family: buf.family().into(),
65            index: buf.index(),
66            handle: buf.handle().into(),
67            parent: buf.parent().into(),
68            info: buf.info(),
69        })
70    }
71}
72
73#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
74pub struct TcHandle {
75    pub major: u16,
76    pub minor: u16,
77}
78
79impl TcHandle {
80    pub const UNSPEC: Self = Self { major: 0, minor: 0 };
81    pub const ROOT: Self = Self {
82        major: u16::MAX,
83        minor: u16::MAX,
84    };
85    pub const INGRESS: Self = Self {
86        major: u16::MAX,
87        minor: 0xfff1,
88    };
89
90    pub const CLSACT: Self = Self::INGRESS;
91
92    pub const MIN_PRIORITY: u16 = 0xFFE0;
93    pub const MIN_INGRESS: u16 = 0xFFF2;
94    pub const MIN_EGRESS: u16 = 0xFFF3;
95}
96
97impl From<u32> for TcHandle {
98    fn from(d: u32) -> Self {
99        let bytes = d.to_be_bytes();
100        Self {
101            major: u16::from_be_bytes([bytes[0], bytes[1]]),
102            minor: u16::from_be_bytes([bytes[2], bytes[3]]),
103        }
104    }
105}
106
107impl From<TcHandle> for u32 {
108    fn from(v: TcHandle) -> u32 {
109        let major_bytes = v.major.to_be_bytes();
110        let minor_bytes = v.minor.to_be_bytes();
111        u32::from_be_bytes([
112            major_bytes[0],
113            major_bytes[1],
114            minor_bytes[0],
115            minor_bytes[1],
116        ])
117    }
118}
119
120impl std::fmt::Display for TcHandle {
121    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122        write!(f, "{}:{}", self.major, self.minor)
123    }
124}