netlink_packet_route/tc/
header.rs

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