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