netlink_packet_route/tc/actions/
mirror.rs
1use netlink_packet_utils::{
10 nla::{DefaultNla, Nla, NlaBuffer},
11 traits::{Emitable, Parseable},
12 DecodeError,
13};
14
15use super::{TcActionGeneric, TcActionGenericBuffer};
16
17#[derive(Debug, PartialEq, Eq, Clone)]
19#[non_exhaustive]
20pub struct TcActionMirror {}
21impl TcActionMirror {
22 pub const KIND: &'static str = "mirred";
24}
25
26const TCA_MIRRED_TM: u16 = 1;
27const TCA_MIRRED_PARMS: u16 = 2;
28
29#[derive(Debug, PartialEq, Eq, Clone)]
31#[non_exhaustive]
32pub enum TcActionMirrorOption {
33 Tm(Vec<u8>),
35 Parms(TcMirror),
37 Other(DefaultNla),
39}
40
41impl Nla for TcActionMirrorOption {
42 fn value_len(&self) -> usize {
43 match self {
44 Self::Tm(bytes) => bytes.len(),
45 Self::Parms(_) => TC_MIRRED_BUF_LEN,
46 Self::Other(attr) => attr.value_len(),
47 }
48 }
49
50 fn emit_value(&self, buffer: &mut [u8]) {
51 match self {
52 Self::Tm(bytes) => buffer.copy_from_slice(bytes.as_slice()),
53 Self::Parms(p) => p.emit(buffer),
54 Self::Other(attr) => attr.emit_value(buffer),
55 }
56 }
57 fn kind(&self) -> u16 {
58 match self {
59 Self::Tm(_) => TCA_MIRRED_TM,
60 Self::Parms(_) => TCA_MIRRED_PARMS,
61 Self::Other(nla) => nla.kind(),
62 }
63 }
64}
65
66impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for TcActionMirrorOption {
67 type Error = DecodeError;
68 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
69 let payload = buf.value();
70 Ok(match buf.kind() {
71 TCA_MIRRED_TM => Self::Tm(payload.to_vec()),
72 TCA_MIRRED_PARMS => {
73 Self::Parms(TcMirror::parse(&TcMirrorBuffer::new_checked(payload)?)?)
74 }
75 _ => Self::Other(DefaultNla::parse(buf)?),
76 })
77 }
78}
79
80const TC_MIRRED_BUF_LEN: usize = TcActionGeneric::BUF_LEN + 8;
81
82#[derive(Debug, PartialEq, Eq, Clone, Default)]
84#[non_exhaustive]
85pub struct TcMirror {
86 pub generic: TcActionGeneric,
88 pub eaction: TcMirrorActionType,
90 pub ifindex: u32,
92}
93
94buffer!(TcMirrorBuffer(TC_MIRRED_BUF_LEN) {
96 generic: (slice, 0..20),
97 eaction: (i32, 20..24),
98 ifindex: (u32, 24..28),
99});
100
101impl Emitable for TcMirror {
102 fn buffer_len(&self) -> usize {
103 TC_MIRRED_BUF_LEN
104 }
105
106 fn emit(&self, buffer: &mut [u8]) {
107 let mut packet = TcMirrorBuffer::new(buffer);
108 self.generic.emit(packet.generic_mut());
109 packet.set_eaction(self.eaction.into());
110 packet.set_ifindex(self.ifindex);
111 }
112}
113
114impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<TcMirrorBuffer<&'a T>> for TcMirror {
115 type Error = DecodeError;
116 fn parse(buf: &TcMirrorBuffer<&T>) -> Result<Self, DecodeError> {
117 Ok(Self {
118 generic: TcActionGeneric::parse(&TcActionGenericBuffer::new(buf.generic()))?,
119 eaction: buf.eaction().into(),
120 ifindex: buf.ifindex(),
121 })
122 }
123}
124
125const TCA_EGRESS_REDIR: i32 = 1;
126const TCA_EGRESS_MIRROR: i32 = 2;
127const TCA_INGRESS_REDIR: i32 = 3;
128const TCA_INGRESS_MIRROR: i32 = 4;
129
130#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
132#[non_exhaustive]
133pub enum TcMirrorActionType {
134 #[default]
135 EgressRedir,
137 EgressMirror,
139 IngressRedir,
141 IngressMirror,
143 Other(i32),
145}
146
147impl From<i32> for TcMirrorActionType {
148 fn from(d: i32) -> Self {
149 match d {
150 TCA_EGRESS_REDIR => Self::EgressRedir,
151 TCA_EGRESS_MIRROR => Self::EgressMirror,
152 TCA_INGRESS_REDIR => Self::IngressRedir,
153 TCA_INGRESS_MIRROR => Self::IngressMirror,
154 _ => Self::Other(d),
155 }
156 }
157}
158
159impl From<TcMirrorActionType> for i32 {
160 fn from(v: TcMirrorActionType) -> i32 {
161 match v {
162 TcMirrorActionType::EgressRedir => TCA_EGRESS_REDIR,
163 TcMirrorActionType::EgressMirror => TCA_EGRESS_MIRROR,
164 TcMirrorActionType::IngressRedir => TCA_INGRESS_REDIR,
165 TcMirrorActionType::IngressMirror => TCA_INGRESS_MIRROR,
166 TcMirrorActionType::Other(d) => d,
167 }
168 }
169}