netlink_packet_route/link/link_info/
geneve.rs

1// SPDX-License-Identifier: MIT
2
3use std::net::{Ipv4Addr, Ipv6Addr};
4
5use netlink_packet_core::{
6    emit_u16_be, emit_u32, emit_u32_be, parse_u16_be, parse_u32, parse_u32_be,
7    parse_u8, DecodeError, DefaultNla, ErrorContext, Nla, NlaBuffer, Parseable,
8};
9
10const IFLA_GENEVE_ID: u16 = 1;
11const IFLA_GENEVE_REMOTE: u16 = 2;
12const IFLA_GENEVE_TTL: u16 = 3;
13const IFLA_GENEVE_TOS: u16 = 4;
14const IFLA_GENEVE_PORT: u16 = 5;
15const IFLA_GENEVE_COLLECT_METADATA: u16 = 6;
16const IFLA_GENEVE_REMOTE6: u16 = 7;
17const IFLA_GENEVE_UDP_CSUM: u16 = 8;
18const IFLA_GENEVE_UDP_ZERO_CSUM6_TX: u16 = 9;
19const IFLA_GENEVE_UDP_ZERO_CSUM6_RX: u16 = 10;
20const IFLA_GENEVE_LABEL: u16 = 11;
21const IFLA_GENEVE_TTL_INHERIT: u16 = 12;
22const IFLA_GENEVE_DF: u16 = 13;
23const IFLA_GENEVE_INNER_PROTO_INHERIT: u16 = 14;
24
25const GENEVE_DF_UNSET: u8 = 0;
26const GENEVE_DF_SET: u8 = 1;
27const GENEVE_DF_INHERIT: u8 = 2;
28
29#[derive(Debug, PartialEq, Eq, Clone, Copy)]
30#[non_exhaustive]
31pub enum GeneveDf {
32    Unset,
33    Set,
34    Inherit,
35    Other(u8),
36}
37
38impl From<u8> for GeneveDf {
39    fn from(d: u8) -> Self {
40        match d {
41            GENEVE_DF_UNSET => Self::Unset,
42            GENEVE_DF_SET => Self::Set,
43            GENEVE_DF_INHERIT => Self::Inherit,
44            _ => Self::Other(d),
45        }
46    }
47}
48
49impl From<GeneveDf> for u8 {
50    fn from(d: GeneveDf) -> Self {
51        match d {
52            GeneveDf::Unset => GENEVE_DF_UNSET,
53            GeneveDf::Set => GENEVE_DF_SET,
54            GeneveDf::Inherit => GENEVE_DF_INHERIT,
55            GeneveDf::Other(value) => value,
56        }
57    }
58}
59
60#[derive(Debug, PartialEq, Eq, Clone)]
61#[non_exhaustive]
62pub enum InfoGeneve {
63    Id(u32),
64    Remote(Ipv4Addr),
65    Remote6(Ipv6Addr),
66    Ttl(u8),
67    Tos(u8),
68    Port(u16),
69    CollectMetadata,
70    UdpCsum(bool),
71    UdpZeroCsum6Tx(bool),
72    UdpZeroCsum6Rx(bool),
73    Label(u32),
74    TtlInherit(bool),
75    Df(GeneveDf),
76    InnerProtoInherit,
77    Other(DefaultNla),
78}
79
80impl Nla for InfoGeneve {
81    fn value_len(&self) -> usize {
82        use self::InfoGeneve::*;
83        match self {
84            Id(_) | Remote(_) | Label(_) => 4,
85            Remote6(_) => 16,
86            Ttl(_) | Tos(_) | UdpCsum(_) | UdpZeroCsum6Tx(_)
87            | UdpZeroCsum6Rx(_) | TtlInherit(_) | Df(_) => 1,
88            Port(_) => 2,
89            CollectMetadata | InnerProtoInherit => 0,
90            Other(nla) => nla.value_len(),
91        }
92    }
93
94    fn emit_value(&self, buffer: &mut [u8]) {
95        use self::InfoGeneve::*;
96        match self {
97            Id(value) => emit_u32(buffer, *value).unwrap(),
98            Remote(value) => buffer.copy_from_slice(&value.octets()),
99            Remote6(value) => buffer.copy_from_slice(&value.octets()),
100            Ttl(value) | Tos(value) => buffer[0] = *value,
101            Port(value) => emit_u16_be(buffer, *value).unwrap(),
102            CollectMetadata | InnerProtoInherit => (),
103            UdpCsum(value)
104            | UdpZeroCsum6Tx(value)
105            | UdpZeroCsum6Rx(value)
106            | TtlInherit(value) => buffer[0] = *value as u8,
107            Label(value) => emit_u32_be(buffer, *value).unwrap(),
108            Df(value) => buffer[0] = (*value).into(),
109            Other(nla) => nla.emit_value(buffer),
110        }
111    }
112
113    fn kind(&self) -> u16 {
114        use self::InfoGeneve::*;
115        match self {
116            Id(_) => IFLA_GENEVE_ID,
117            Remote(_) => IFLA_GENEVE_REMOTE,
118            Remote6(_) => IFLA_GENEVE_REMOTE6,
119            Ttl(_) => IFLA_GENEVE_TTL,
120            Tos(_) => IFLA_GENEVE_TOS,
121            Port(_) => IFLA_GENEVE_PORT,
122            CollectMetadata => IFLA_GENEVE_COLLECT_METADATA,
123            UdpCsum(_) => IFLA_GENEVE_UDP_CSUM,
124            UdpZeroCsum6Tx(_) => IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
125            UdpZeroCsum6Rx(_) => IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
126            Label(_) => IFLA_GENEVE_LABEL,
127            TtlInherit(_) => IFLA_GENEVE_TTL_INHERIT,
128            Df(_) => IFLA_GENEVE_DF,
129            InnerProtoInherit => IFLA_GENEVE_INNER_PROTO_INHERIT,
130            Other(nla) => nla.kind(),
131        }
132    }
133}
134
135impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoGeneve {
136    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
137        use self::InfoGeneve::*;
138        let payload = buf.value();
139        Ok(match buf.kind() {
140            IFLA_GENEVE_ID => {
141                Id(parse_u32(payload)
142                    .context("invalid IFLA_GENEVE_ID value")?)
143            }
144            IFLA_GENEVE_REMOTE => {
145                if payload.len() == 4 {
146                    let mut data = [0u8; 4];
147                    data.copy_from_slice(&payload[0..4]);
148                    Remote(Ipv4Addr::from(data))
149                } else {
150                    return Err(DecodeError::from(format!(
151                        "Invalid IFLA_GENEVE_REMOTE, got unexpected length of \
152                         IPv4 address payload {payload:?}"
153                    )));
154                }
155            }
156            IFLA_GENEVE_REMOTE6 => {
157                if payload.len() == 16 {
158                    let mut data = [0u8; 16];
159                    data.copy_from_slice(&payload[0..16]);
160                    Remote6(Ipv6Addr::from(data))
161                } else {
162                    return Err(DecodeError::from(format!(
163                        "Invalid IFLA_GENEVE_REMOTE6, got unexpected length \
164                         of IPv6 address payload {payload:?}"
165                    )));
166                }
167            }
168            IFLA_GENEVE_TTL => {
169                Ttl(parse_u8(payload)
170                    .context("invalid IFLA_GENEVE_TTL value")?)
171            }
172            IFLA_GENEVE_TOS => {
173                Tos(parse_u8(payload)
174                    .context("invalid IFLA_GENEVE_TOS value")?)
175            }
176            IFLA_GENEVE_PORT => Port(
177                parse_u16_be(payload)
178                    .context("invalid IFLA_GENEVE_PORT value")?,
179            ),
180            IFLA_GENEVE_COLLECT_METADATA => CollectMetadata,
181            IFLA_GENEVE_UDP_CSUM => UdpCsum(
182                parse_u8(payload)
183                    .context("invalid IFLA_GENEVE_UDP_CSUM value")?
184                    > 0,
185            ),
186            IFLA_GENEVE_UDP_ZERO_CSUM6_TX => UdpZeroCsum6Tx(
187                parse_u8(payload)
188                    .context("invalid IFLA_GENEVE_UDP_ZERO_CSUM6_TX value")?
189                    > 0,
190            ),
191            IFLA_GENEVE_UDP_ZERO_CSUM6_RX => UdpZeroCsum6Rx(
192                parse_u8(payload)
193                    .context("invalid IFLA_GENEVE_UDP_ZERO_CSUM6_RX value")?
194                    > 0,
195            ),
196            IFLA_GENEVE_LABEL => Label(
197                parse_u32_be(payload)
198                    .context("invalid IFLA_GENEVE_LABEL value")?,
199            ),
200            IFLA_GENEVE_TTL_INHERIT => TtlInherit(
201                parse_u8(payload)
202                    .context("invalid IFLA_GENEVE_TTL_INHERIT value")?
203                    > 0,
204            ),
205            IFLA_GENEVE_DF => Df(parse_u8(payload)
206                .context("invalid IFLA_GENEVE_DF value")?
207                .into()),
208            IFLA_GENEVE_INNER_PROTO_INHERIT => InnerProtoInherit,
209            kind => Other(
210                DefaultNla::parse(buf)
211                    .context(format!("unknown NLA type {kind}"))?,
212            ),
213        })
214    }
215}