netlink_packet_route/rtnl/tc/nlas/action/
mirred.rs

1// SPDX-License-Identifier: MIT
2
3/// Mirred action
4///
5/// The mirred action allows packet mirroring (copying) or
6/// redirecting (stealing) the packet it receives. Mirroring is what
7/// is sometimes referred to as Switch Port Analyzer (SPAN) and is
8/// commonly used to analyze and/or debug flows.
9use crate::{
10    nlas::{self, DefaultNla, NlaBuffer},
11    tc::{constants::*, TC_GEN_BUF_LEN},
12    traits::{Emitable, Parseable},
13    DecodeError,
14};
15
16pub const KIND: &str = "mirred";
17pub const TC_MIRRED_BUF_LEN: usize = TC_GEN_BUF_LEN + 8;
18
19#[derive(Debug, PartialEq, Eq, Clone)]
20pub enum Nla {
21    Unspec(Vec<u8>),
22    Tm(Vec<u8>),
23    Parms(TcMirred),
24    Other(DefaultNla),
25}
26
27impl nlas::Nla for Nla {
28    fn value_len(&self) -> usize {
29        use self::Nla::*;
30        match self {
31            Unspec(bytes) | Tm(bytes) => bytes.len(),
32            Parms(_) => TC_MIRRED_BUF_LEN,
33            Other(attr) => attr.value_len(),
34        }
35    }
36
37    fn emit_value(&self, buffer: &mut [u8]) {
38        use self::Nla::*;
39        match self {
40            Unspec(bytes) | Tm(bytes) => buffer.copy_from_slice(bytes.as_slice()),
41            Parms(p) => p.emit(buffer),
42            Other(attr) => attr.emit_value(buffer),
43        }
44    }
45    fn kind(&self) -> u16 {
46        use self::Nla::*;
47        match self {
48            Unspec(_) => TCA_MIRRED_UNSPEC,
49            Tm(_) => TCA_MIRRED_TM,
50            Parms(_) => TCA_MIRRED_PARMS,
51            Other(nla) => nla.kind(),
52        }
53    }
54}
55
56impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Nla {
57    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
58        use self::Nla::*;
59        let payload = buf.value();
60        Ok(match buf.kind() {
61            TCA_MIRRED_UNSPEC => Unspec(payload.to_vec()),
62            TCA_MIRRED_TM => Tm(payload.to_vec()),
63            TCA_MIRRED_PARMS => Parms(TcMirred::parse(&TcMirredBuffer::new_checked(payload)?)?),
64            _ => Other(DefaultNla::parse(buf)?),
65        })
66    }
67}
68
69#[derive(Debug, PartialEq, Eq, Clone, Default)]
70pub struct TcMirred {
71    pub index: u32,
72    pub capab: u32,
73    pub action: i32,
74    pub refcnt: i32,
75    pub bindcnt: i32,
76
77    pub eaction: i32,
78    pub ifindex: u32,
79}
80
81buffer!(TcMirredBuffer(TC_MIRRED_BUF_LEN) {
82    index: (u32, 0..4),
83    capab: (u32, 4..8),
84    action: (i32, 8..12),
85    refcnt: (i32, 12..16),
86    bindcnt: (i32, 16..20),
87    eaction: (i32, TC_GEN_BUF_LEN..(TC_GEN_BUF_LEN + 4)),
88    ifindex: (u32, (TC_GEN_BUF_LEN + 4)..TC_MIRRED_BUF_LEN),
89});
90
91impl Emitable for TcMirred {
92    fn buffer_len(&self) -> usize {
93        TC_MIRRED_BUF_LEN
94    }
95
96    fn emit(&self, buffer: &mut [u8]) {
97        let mut packet = TcMirredBuffer::new(buffer);
98        packet.set_index(self.index);
99        packet.set_capab(self.capab);
100        packet.set_action(self.action);
101        packet.set_refcnt(self.refcnt);
102        packet.set_bindcnt(self.bindcnt);
103
104        packet.set_eaction(self.eaction);
105        packet.set_ifindex(self.ifindex);
106    }
107}
108
109impl<T: AsRef<[u8]>> Parseable<TcMirredBuffer<T>> for TcMirred {
110    fn parse(buf: &TcMirredBuffer<T>) -> Result<Self, DecodeError> {
111        Ok(Self {
112            index: buf.index(),
113            capab: buf.capab(),
114            action: buf.action(),
115            refcnt: buf.refcnt(),
116            bindcnt: buf.bindcnt(),
117            eaction: buf.eaction(),
118            ifindex: buf.ifindex(),
119        })
120    }
121}