netlink_packet_route/tc/actions/
tunnel_key.rs

1// SPDX-License-Identifier: MIT
2
3use std::net::{Ipv4Addr, Ipv6Addr};
4
5use netlink_packet_core::{
6    emit_u16_be, emit_u32_be, parse_u16_be, parse_u32_be, parse_u8,
7    DecodeError, DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer, Parseable,
8};
9
10use super::{
11    TcActionGeneric, TcActionGenericBuffer, Tcf, TcfBuffer, TC_TCF_BUF_LEN,
12};
13/// set tunnel key
14///
15/// The set_tunnel action allows to set tunnel encap applied
16/// at the last stage of action processing
17use crate::ip::{parse_ipv4_addr, parse_ipv6_addr};
18
19#[derive(Debug, PartialEq, Eq, Clone)]
20#[non_exhaustive]
21pub struct TcActionTunnelKey {}
22impl TcActionTunnelKey {
23    pub const KIND: &'static str = "tunnel_key";
24}
25
26const TCA_TUNNEL_KEY_TM: u16 = 1;
27const TCA_TUNNEL_KEY_PARMS: u16 = 2;
28const TCA_TUNNEL_KEY_ENC_IPV4_SRC: u16 = 3;
29const TCA_TUNNEL_KEY_ENC_IPV4_DST: u16 = 4;
30const TCA_TUNNEL_KEY_ENC_IPV6_SRC: u16 = 5;
31const TCA_TUNNEL_KEY_ENC_IPV6_DST: u16 = 6;
32const TCA_TUNNEL_KEY_ENC_KEY_ID: u16 = 7;
33// const TCA_TUNNEL_KEY_PAD: u16 = 8;
34const TCA_TUNNEL_KEY_ENC_DST_PORT: u16 = 9;
35const TCA_TUNNEL_KEY_NO_CSUM: u16 = 10;
36// const TCA_TUNNEL_KEY_ENC_OPTS: u16 = 11;
37const TCA_TUNNEL_KEY_ENC_TOS: u16 = 12;
38const TCA_TUNNEL_KEY_ENC_TTL: u16 = 13;
39// const TCA_TUNNEL_KEY_NO_FRAG: u16 = 14;
40
41#[derive(Debug, PartialEq, Eq, Clone)]
42#[non_exhaustive]
43pub enum TcActionTunnelKeyOption {
44    Tm(Tcf),
45    Parms(TcTunnelKey),
46    EncIpv4Src(Ipv4Addr),
47    EncIpv4Dst(Ipv4Addr),
48    EncIpv6Src(Ipv6Addr),
49    EncIpv6Dst(Ipv6Addr),
50    EncKeyId(u32),
51    EncDstPort(u16),
52    EncTos(u8),
53    EncTtl(u8),
54    NoCsum(bool),
55    Other(DefaultNla),
56}
57
58impl Nla for TcActionTunnelKeyOption {
59    fn value_len(&self) -> usize {
60        match self {
61            Self::Tm(_) => TC_TCF_BUF_LEN,
62            Self::Parms(_) => TC_TUNNEL_KEY_BUF_LEN,
63            Self::EncIpv4Src(_) | Self::EncIpv4Dst(_) => 4,
64            Self::EncIpv6Src(_) | Self::EncIpv6Dst(_) => 16,
65            Self::EncKeyId(_) => 4,
66            Self::EncDstPort(_) => 2,
67            Self::EncTos(_) | Self::EncTtl(_) => 1,
68            Self::NoCsum(_) => 1,
69            Self::Other(attr) => attr.value_len(),
70        }
71    }
72
73    fn emit_value(&self, buffer: &mut [u8]) {
74        match self {
75            Self::Tm(p) => p.emit(buffer),
76            Self::Parms(p) => p.emit(buffer),
77            Self::EncIpv4Src(ip) | Self::EncIpv4Dst(ip) => {
78                buffer.copy_from_slice(&ip.octets())
79            }
80            Self::EncIpv6Src(ip) | Self::EncIpv6Dst(ip) => {
81                buffer.copy_from_slice(&ip.octets())
82            }
83            Self::EncKeyId(i) => emit_u32_be(buffer, *i).unwrap(),
84            Self::EncDstPort(i) => emit_u16_be(buffer, *i).unwrap(),
85            Self::EncTos(i) => buffer[0] = *i,
86            Self::EncTtl(i) => buffer[0] = *i,
87            Self::NoCsum(i) => buffer[0] = *i as u8,
88            Self::Other(attr) => attr.emit_value(buffer),
89        }
90    }
91    fn kind(&self) -> u16 {
92        match self {
93            Self::Tm(_) => TCA_TUNNEL_KEY_TM,
94            Self::Parms(_) => TCA_TUNNEL_KEY_PARMS,
95            Self::EncIpv4Src(_) => TCA_TUNNEL_KEY_ENC_IPV4_SRC,
96            Self::EncIpv4Dst(_) => TCA_TUNNEL_KEY_ENC_IPV4_DST,
97            Self::EncIpv6Src(_) => TCA_TUNNEL_KEY_ENC_IPV6_SRC,
98            Self::EncIpv6Dst(_) => TCA_TUNNEL_KEY_ENC_IPV6_DST,
99            Self::EncKeyId(_) => TCA_TUNNEL_KEY_ENC_KEY_ID,
100            Self::EncDstPort(_) => TCA_TUNNEL_KEY_ENC_DST_PORT,
101            Self::EncTos(_) => TCA_TUNNEL_KEY_ENC_TOS,
102            Self::EncTtl(_) => TCA_TUNNEL_KEY_ENC_TTL,
103            Self::NoCsum(_) => TCA_TUNNEL_KEY_NO_CSUM,
104            Self::Other(nla) => nla.kind(),
105        }
106    }
107}
108
109impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
110    for TcActionTunnelKeyOption
111{
112    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
113        let payload = buf.value();
114        Ok(match buf.kind() {
115            TCA_TUNNEL_KEY_TM => {
116                Self::Tm(Tcf::parse(&TcfBuffer::new_checked(payload)?)?)
117            }
118            TCA_TUNNEL_KEY_PARMS => Self::Parms(TcTunnelKey::parse(
119                &TcTunnelKeyBuffer::new_checked(payload)?,
120            )?),
121            TCA_TUNNEL_KEY_ENC_IPV4_SRC => Self::EncIpv4Src(
122                parse_ipv4_addr(payload)
123                    .context("failed to parse TCA_TUNNEL_KEY_ENC_IPV4_SRC")?,
124            ),
125            TCA_TUNNEL_KEY_ENC_IPV4_DST => Self::EncIpv4Dst(
126                parse_ipv4_addr(payload)
127                    .context("failed to parse TCA_TUNNEL_KEY_ENC_IPV4_DST")?,
128            ),
129            TCA_TUNNEL_KEY_ENC_IPV6_SRC => Self::EncIpv6Src(
130                parse_ipv6_addr(payload)
131                    .context("failed to parse TCA_TUNNEL_KEY_ENC_IPV6_SRC")?,
132            ),
133            TCA_TUNNEL_KEY_ENC_IPV6_DST => Self::EncIpv6Dst(
134                parse_ipv6_addr(payload)
135                    .context("failed to parse TCA_TUNNEL_KEY_ENC_IPV6_DST")?,
136            ),
137            TCA_TUNNEL_KEY_ENC_KEY_ID => Self::EncKeyId(
138                parse_u32_be(payload)
139                    .context("failed to parse TCA_TUNNEL_KEY_ENC_KEY_ID")?,
140            ),
141            TCA_TUNNEL_KEY_ENC_DST_PORT => Self::EncDstPort(
142                parse_u16_be(payload)
143                    .context("failed to parse TCA_TUNNEL_KEY_ENC_DST_PORT")?,
144            ),
145            TCA_TUNNEL_KEY_ENC_TOS => Self::EncTos(
146                parse_u8(payload)
147                    .context("failed to parse TCA_TUNNEL_KEY_ENC_TOS")?,
148            ),
149            TCA_TUNNEL_KEY_ENC_TTL => Self::EncTtl(
150                parse_u8(payload)
151                    .context("failed to parse TCA_TUNNEL_KEY_ENC_TTL")?,
152            ),
153            TCA_TUNNEL_KEY_NO_CSUM => Self::NoCsum(
154                parse_u8(payload)
155                    .context("invalid TCA_TUNNEL_KEY_NO_CSUM value")?
156                    != 0,
157            ),
158            _ => Self::Other(DefaultNla::parse(buf)?),
159        })
160    }
161}
162
163const TC_TUNNEL_KEY_BUF_LEN: usize = TcActionGeneric::BUF_LEN + 4;
164
165#[derive(Debug, PartialEq, Eq, Clone, Default)]
166pub struct TcTunnelKey {
167    pub generic: TcActionGeneric,
168    pub t_action: i32,
169}
170
171// kernel struct `tc_tunnel_key`
172buffer!(TcTunnelKeyBuffer(TC_TUNNEL_KEY_BUF_LEN) {
173    generic: (slice, 0..20),
174    t_action: (i32, 20..24),
175});
176
177impl Emitable for TcTunnelKey {
178    fn buffer_len(&self) -> usize {
179        TC_TUNNEL_KEY_BUF_LEN
180    }
181
182    fn emit(&self, buffer: &mut [u8]) {
183        let mut packet = TcTunnelKeyBuffer::new(buffer);
184        self.generic.emit(packet.generic_mut());
185        packet.set_t_action(self.t_action);
186    }
187}
188
189impl<T: AsRef<[u8]> + ?Sized> Parseable<TcTunnelKeyBuffer<&T>> for TcTunnelKey {
190    fn parse(buf: &TcTunnelKeyBuffer<&T>) -> Result<Self, DecodeError> {
191        Ok(Self {
192            generic: TcActionGeneric::parse(&TcActionGenericBuffer::new(
193                buf.generic(),
194            ))?,
195            t_action: buf.t_action(),
196        })
197    }
198}