netlink_packet_route/tc/actions/
mirror.rs1use netlink_packet_core::{
10 DecodeError, DefaultNla, Emitable, Nla, NlaBuffer, Parseable,
11};
12
13use super::{
14 TcActionGeneric, TcActionGenericBuffer, Tcf, TcfBuffer, TC_TCF_BUF_LEN,
15};
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(Tcf),
35 Parms(TcMirror),
37 Other(DefaultNla),
39}
40
41impl Nla for TcActionMirrorOption {
42 fn value_len(&self) -> usize {
43 match self {
44 Self::Tm(_) => TC_TCF_BUF_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(p) => p.emit(buffer),
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>>
67 for TcActionMirrorOption
68{
69 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
70 let payload = buf.value();
71 Ok(match buf.kind() {
72 TCA_MIRRED_TM => {
73 Self::Tm(Tcf::parse(&TcfBuffer::new_checked(payload)?)?)
74 }
75 TCA_MIRRED_PARMS => Self::Parms(TcMirror::parse(
76 &TcMirrorBuffer::new_checked(payload)?,
77 )?),
78 _ => Self::Other(DefaultNla::parse(buf)?),
79 })
80 }
81}
82
83const TC_MIRRED_BUF_LEN: usize = TcActionGeneric::BUF_LEN + 8;
84
85#[derive(Debug, PartialEq, Eq, Clone, Default)]
87#[non_exhaustive]
88pub struct TcMirror {
89 pub generic: TcActionGeneric,
91 pub eaction: TcMirrorActionType,
93 pub ifindex: u32,
95}
96
97buffer!(TcMirrorBuffer(TC_MIRRED_BUF_LEN) {
99 generic: (slice, 0..20),
100 eaction: (i32, 20..24),
101 ifindex: (u32, 24..28),
102});
103
104impl Emitable for TcMirror {
105 fn buffer_len(&self) -> usize {
106 TC_MIRRED_BUF_LEN
107 }
108
109 fn emit(&self, buffer: &mut [u8]) {
110 let mut packet = TcMirrorBuffer::new(buffer);
111 self.generic.emit(packet.generic_mut());
112 packet.set_eaction(self.eaction.into());
113 packet.set_ifindex(self.ifindex);
114 }
115}
116
117impl<T: AsRef<[u8]> + ?Sized> Parseable<TcMirrorBuffer<&T>> for TcMirror {
118 fn parse(buf: &TcMirrorBuffer<&T>) -> Result<Self, DecodeError> {
119 Ok(Self {
120 generic: TcActionGeneric::parse(&TcActionGenericBuffer::new(
121 buf.generic(),
122 ))?,
123 eaction: buf.eaction().into(),
124 ifindex: buf.ifindex(),
125 })
126 }
127}
128
129const TCA_EGRESS_REDIR: i32 = 1;
130const TCA_EGRESS_MIRROR: i32 = 2;
131const TCA_INGRESS_REDIR: i32 = 3;
132const TCA_INGRESS_MIRROR: i32 = 4;
133
134#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
136#[non_exhaustive]
137pub enum TcMirrorActionType {
138 #[default]
139 EgressRedir,
141 EgressMirror,
143 IngressRedir,
145 IngressMirror,
147 Other(i32),
149}
150
151impl From<i32> for TcMirrorActionType {
152 fn from(d: i32) -> Self {
153 match d {
154 TCA_EGRESS_REDIR => Self::EgressRedir,
155 TCA_EGRESS_MIRROR => Self::EgressMirror,
156 TCA_INGRESS_REDIR => Self::IngressRedir,
157 TCA_INGRESS_MIRROR => Self::IngressMirror,
158 _ => Self::Other(d),
159 }
160 }
161}
162
163impl From<TcMirrorActionType> for i32 {
164 fn from(v: TcMirrorActionType) -> i32 {
165 match v {
166 TcMirrorActionType::EgressRedir => TCA_EGRESS_REDIR,
167 TcMirrorActionType::EgressMirror => TCA_EGRESS_MIRROR,
168 TcMirrorActionType::IngressRedir => TCA_INGRESS_REDIR,
169 TcMirrorActionType::IngressMirror => TCA_INGRESS_MIRROR,
170 TcMirrorActionType::Other(d) => d,
171 }
172 }
173}