netlink_packet_route/tc/actions/
tunnel_key.rs

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