1
1
// SPDX-License-Identifier: MIT
2
2
3
+ use std:: net:: Ipv6Addr ;
4
+
3
5
use anyhow:: Context ;
6
+ use byteorder:: { BigEndian , ByteOrder , NetworkEndian } ;
4
7
use netlink_packet_utils:: {
5
8
nla:: { DefaultNla , Nla , NlaBuffer , NlasIterator } ,
9
+ parsers:: { parse_u16_be, parse_u8} ,
6
10
traits:: { Emitable , Parseable , ParseableParametrized } ,
7
11
DecodeError ,
8
12
} ;
9
13
14
+ use crate :: ip:: parse_ipv6_addr;
15
+
10
16
use super :: RouteMplsIpTunnel ;
11
17
12
18
const LWTUNNEL_ENCAP_NONE : u16 = 0 ;
@@ -21,6 +27,20 @@ const LWTUNNEL_ENCAP_RPL: u16 = 8;
21
27
const LWTUNNEL_ENCAP_IOAM6 : u16 = 9 ;
22
28
const LWTUNNEL_ENCAP_XFRM : u16 = 10 ;
23
29
30
+ const LWTUNNEL_IP6_UNSPEC : u16 = 0 ;
31
+ const LWTUNNEL_IP6_ID : u16 = 1 ;
32
+ const LWTUNNEL_IP6_DST : u16 = 2 ;
33
+ const LWTUNNEL_IP6_SRC : u16 = 3 ;
34
+ const LWTUNNEL_IP6_HOPLIMIT : u16 = 4 ;
35
+ const LWTUNNEL_IP6_TC : u16 = 5 ;
36
+ const LWTUNNEL_IP6_FLAGS : u16 = 6 ;
37
+ //const LWTUNNEL_IP6_PAD: u16 = 7;
38
+ //const LWTUNNEL_IP6_OPTS: u16 = 8;
39
+
40
+ const TUNNEL_CSUM : u16 = 1 ;
41
+ const TUNNEL_KEY : u16 = 4 ;
42
+ const TUNNEL_SEQ : u16 = 8 ;
43
+
24
44
#[ derive( Debug , PartialEq , Eq , Clone , Copy , Default ) ]
25
45
#[ non_exhaustive]
26
46
pub enum RouteLwEnCapType {
@@ -106,31 +126,160 @@ impl std::fmt::Display for RouteLwEnCapType {
106
126
}
107
127
}
108
128
129
+ #[ derive( Debug , PartialEq , Eq , Clone , Copy , Default ) ]
130
+ pub enum RouteIp6Tunnel {
131
+ #[ default]
132
+ Unspecified ,
133
+ Id ( u64 ) ,
134
+ Destination ( Ipv6Addr ) ,
135
+ Source ( Ipv6Addr ) ,
136
+ Hoplimit ( u8 ) ,
137
+ Tc ( u8 ) ,
138
+ Flags ( u16 ) ,
139
+ }
140
+
141
+ impl std:: fmt:: Display for RouteIp6Tunnel {
142
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
143
+ match self {
144
+ Self :: Unspecified => write ! ( f, "unspecified" ) ,
145
+ Self :: Id ( id) => write ! ( f, "id {id}" ) ,
146
+ Self :: Destination ( dst) => write ! ( f, "dst {dst}" ) ,
147
+ Self :: Source ( src) => write ! ( f, "src, {src}" ) ,
148
+ Self :: Hoplimit ( hoplimit) => write ! ( f, "hoplimit {hoplimit}" ) ,
149
+ Self :: Tc ( tc) => write ! ( f, "tc {tc}" ) ,
150
+ Self :: Flags ( flags) => {
151
+ if flags & TUNNEL_KEY != 0 {
152
+ write ! ( f, "key " ) ?;
153
+ }
154
+ if flags & TUNNEL_CSUM != 0 {
155
+ write ! ( f, "csum " ) ?;
156
+ }
157
+
158
+ if flags & TUNNEL_SEQ != 0 {
159
+ write ! ( f, "seq " ) ?;
160
+ }
161
+
162
+ Ok ( ( ) )
163
+ }
164
+ }
165
+ }
166
+ }
167
+
168
+ impl Nla for RouteIp6Tunnel {
169
+ fn value_len ( & self ) -> usize {
170
+ match self {
171
+ Self :: Unspecified => 0 ,
172
+ Self :: Id ( _) => const { size_of :: < u64 > ( ) } ,
173
+ Self :: Destination ( _) => const { size_of :: < Ipv6Addr > ( ) } ,
174
+ Self :: Source ( _) => const { size_of :: < Ipv6Addr > ( ) } ,
175
+ Self :: Hoplimit ( _) => const { size_of :: < u8 > ( ) } ,
176
+ Self :: Tc ( _) => const { size_of :: < u8 > ( ) } ,
177
+ Self :: Flags ( _) => const { size_of :: < u16 > ( ) } ,
178
+ }
179
+ }
180
+
181
+ fn kind ( & self ) -> u16 {
182
+ match self {
183
+ Self :: Unspecified => LWTUNNEL_IP6_UNSPEC ,
184
+ Self :: Id ( _) => LWTUNNEL_IP6_ID ,
185
+ Self :: Destination ( _) => LWTUNNEL_IP6_DST ,
186
+ Self :: Source ( _) => LWTUNNEL_IP6_SRC ,
187
+ Self :: Hoplimit ( _) => LWTUNNEL_IP6_HOPLIMIT ,
188
+ Self :: Tc ( _) => LWTUNNEL_IP6_TC ,
189
+ Self :: Flags ( _) => LWTUNNEL_IP6_FLAGS ,
190
+ }
191
+ }
192
+
193
+ fn emit_value ( & self , buffer : & mut [ u8 ] ) {
194
+ match self {
195
+ Self :: Unspecified => { }
196
+ Self :: Id ( id) => NetworkEndian :: write_u64 ( buffer, * id) ,
197
+ Self :: Destination ( ip) | Self :: Source ( ip) => {
198
+ buffer. copy_from_slice ( & ip. octets ( ) ) ;
199
+ }
200
+ Self :: Hoplimit ( value) | Self :: Tc ( value) => buffer[ 0 ] = * value,
201
+ Self :: Flags ( flags) => BigEndian :: write_u16 ( buffer, * flags) ,
202
+ }
203
+ }
204
+ }
205
+
206
+ // should probably be in utils
207
+ fn parse_u64_be ( payload : & [ u8 ] ) -> Result < u64 , DecodeError > {
208
+ if payload. len ( ) != size_of :: < u64 > ( ) {
209
+ return Err ( format ! ( "invalid u64: {payload:?}" ) . into ( ) ) ;
210
+ }
211
+ Ok ( BigEndian :: read_u64 ( payload) )
212
+ }
213
+
214
+ impl < ' a , T > Parseable < NlaBuffer < & ' a T > > for RouteIp6Tunnel
215
+ where
216
+ T : AsRef < [ u8 ] > + ?Sized ,
217
+ {
218
+ fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
219
+ let payload = buf. value ( ) ;
220
+ Ok ( match buf. kind ( ) {
221
+ LWTUNNEL_IP6_UNSPEC => Self :: Unspecified ,
222
+ LWTUNNEL_IP6_ID => Self :: Id (
223
+ parse_u64_be ( payload)
224
+ . context ( "invalid LWTUNNEL_IP6_ID value" ) ?,
225
+ ) ,
226
+ LWTUNNEL_IP6_DST => Self :: Destination (
227
+ parse_ipv6_addr ( payload)
228
+ . context ( "invalid LWTUNNEL_IP6_DST value" ) ?,
229
+ ) ,
230
+ LWTUNNEL_IP6_SRC => Self :: Source (
231
+ parse_ipv6_addr ( payload)
232
+ . context ( "invalid LWTUNNEL_IP6_SRC value" ) ?,
233
+ ) ,
234
+ LWTUNNEL_IP6_HOPLIMIT => Self :: Hoplimit (
235
+ parse_u8 ( payload)
236
+ . context ( "invalid LWTUNNEL_IP6_HOPLIMIT value" ) ?,
237
+ ) ,
238
+ LWTUNNEL_IP6_TC => Self :: Tc (
239
+ parse_u8 ( payload) . context ( "invalid LWTUNNEL_IP6_TC value" ) ?,
240
+ ) ,
241
+ LWTUNNEL_IP6_FLAGS => Self :: Flags (
242
+ parse_u16_be ( payload)
243
+ . context ( "invalid LWTUNNEL_IP6_FLAGS value" ) ?,
244
+ ) ,
245
+ _ => {
246
+ return Err ( DecodeError :: from (
247
+ "invalid NLA value (unknown type) value" ,
248
+ ) )
249
+ }
250
+ } )
251
+ }
252
+ }
253
+
109
254
#[ derive( Debug , PartialEq , Eq , Clone ) ]
110
255
#[ non_exhaustive]
111
256
pub enum RouteLwTunnelEncap {
112
257
Mpls ( RouteMplsIpTunnel ) ,
258
+ Ip6 ( RouteIp6Tunnel ) ,
113
259
Other ( DefaultNla ) ,
114
260
}
115
261
116
262
impl Nla for RouteLwTunnelEncap {
117
263
fn value_len ( & self ) -> usize {
118
264
match self {
119
265
Self :: Mpls ( v) => v. value_len ( ) ,
266
+ Self :: Ip6 ( v) => v. value_len ( ) ,
120
267
Self :: Other ( v) => v. value_len ( ) ,
121
268
}
122
269
}
123
270
124
271
fn emit_value ( & self , buffer : & mut [ u8 ] ) {
125
272
match self {
126
273
Self :: Mpls ( v) => v. emit_value ( buffer) ,
274
+ Self :: Ip6 ( v) => v. emit_value ( buffer) ,
127
275
Self :: Other ( v) => v. emit_value ( buffer) ,
128
276
}
129
277
}
130
278
131
279
fn kind ( & self ) -> u16 {
132
280
match self {
133
281
Self :: Mpls ( v) => v. kind ( ) ,
282
+ Self :: Ip6 ( v) => v. kind ( ) ,
134
283
Self :: Other ( v) => v. kind ( ) ,
135
284
}
136
285
}
@@ -149,6 +298,7 @@ where
149
298
RouteLwEnCapType :: Mpls => {
150
299
Self :: Mpls ( RouteMplsIpTunnel :: parse ( buf) ?)
151
300
}
301
+ RouteLwEnCapType :: Ip6 => Self :: Ip6 ( RouteIp6Tunnel :: parse ( buf) ?) ,
152
302
_ => Self :: Other ( DefaultNla :: parse ( buf) ?) ,
153
303
} )
154
304
}
0 commit comments