netlink_packet_route/tc/
header.rs

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