1
1
// SPDX-License-Identifier: MIT
2
2
3
+ use std:: { fmt:: Debug , 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 , RouteSeg6IpTunnel } ;
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 IP_TUNNEL_CSUM_BIT : u16 = 1 ;
41
+ const IP_TUNNEL_KEY_BIT : u16 = 4 ;
42
+ const IP_TUNNEL_SEQ_BIT : u16 = 8 ;
43
+
24
44
#[ derive( Debug , PartialEq , Eq , Clone , Copy , Default ) ]
25
45
#[ non_exhaustive]
26
46
pub enum RouteLwEnCapType {
@@ -106,11 +126,152 @@ impl std::fmt::Display for RouteLwEnCapType {
106
126
}
107
127
}
108
128
129
+ #[ derive( Debug , PartialEq , Eq , Clone , Default ) ]
130
+ #[ non_exhaustive]
131
+ pub enum RouteIp6Tunnel {
132
+ #[ default]
133
+ Unspecified ,
134
+ Id ( u64 ) ,
135
+ Destination ( Ipv6Addr ) ,
136
+ Source ( Ipv6Addr ) ,
137
+ Hoplimit ( u8 ) ,
138
+ Tc ( u8 ) ,
139
+ Flags ( RouteIp6TunnelFlags ) ,
140
+ Other ( DefaultNla ) ,
141
+ }
142
+
143
+ bitflags ! {
144
+ #[ non_exhaustive]
145
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
146
+ pub struct RouteIp6TunnelFlags : u16 {
147
+ const Key = IP_TUNNEL_KEY_BIT ;
148
+ const Checksum = IP_TUNNEL_CSUM_BIT ;
149
+ const Sequence = IP_TUNNEL_SEQ_BIT ;
150
+ const _ = !0 ;
151
+ }
152
+ }
153
+
154
+ impl std:: fmt:: Display for RouteIp6Tunnel {
155
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
156
+ match self {
157
+ Self :: Unspecified => write ! ( f, "unspecified" ) ,
158
+ Self :: Id ( id) => write ! ( f, "id {id}" ) ,
159
+ Self :: Destination ( dst) => write ! ( f, "dst {dst}" ) ,
160
+ Self :: Source ( src) => write ! ( f, "src, {src}" ) ,
161
+ Self :: Hoplimit ( hoplimit) => write ! ( f, "hoplimit {hoplimit}" ) ,
162
+ Self :: Tc ( tc) => write ! ( f, "tc {tc}" ) ,
163
+ Self :: Flags ( flags) => {
164
+ if flags. contains ( RouteIp6TunnelFlags :: Key ) {
165
+ write ! ( f, "key " ) ?;
166
+ }
167
+ if flags. contains ( RouteIp6TunnelFlags :: Checksum ) {
168
+ write ! ( f, "csum " ) ?;
169
+ }
170
+
171
+ if flags. contains ( RouteIp6TunnelFlags :: Sequence ) {
172
+ write ! ( f, "seq " ) ?;
173
+ }
174
+
175
+ Ok ( ( ) )
176
+ }
177
+ Self :: Other ( other) => other. fmt ( f) ,
178
+ }
179
+ }
180
+ }
181
+
182
+ impl Nla for RouteIp6Tunnel {
183
+ fn value_len ( & self ) -> usize {
184
+ match self {
185
+ Self :: Unspecified => 0 ,
186
+ Self :: Id ( _) => const { size_of :: < u64 > ( ) } ,
187
+ Self :: Destination ( _) => const { size_of :: < Ipv6Addr > ( ) } ,
188
+ Self :: Source ( _) => const { size_of :: < Ipv6Addr > ( ) } ,
189
+ Self :: Hoplimit ( _) => const { size_of :: < u8 > ( ) } ,
190
+ Self :: Tc ( _) => const { size_of :: < u8 > ( ) } ,
191
+ Self :: Flags ( _) => const { size_of :: < u16 > ( ) } ,
192
+ Self :: Other ( _) => const { size_of :: < DefaultNla > ( ) } ,
193
+ }
194
+ }
195
+
196
+ fn kind ( & self ) -> u16 {
197
+ match self {
198
+ Self :: Unspecified => LWTUNNEL_IP6_UNSPEC ,
199
+ Self :: Id ( _) => LWTUNNEL_IP6_ID ,
200
+ Self :: Destination ( _) => LWTUNNEL_IP6_DST ,
201
+ Self :: Source ( _) => LWTUNNEL_IP6_SRC ,
202
+ Self :: Hoplimit ( _) => LWTUNNEL_IP6_HOPLIMIT ,
203
+ Self :: Tc ( _) => LWTUNNEL_IP6_TC ,
204
+ Self :: Flags ( _) => LWTUNNEL_IP6_FLAGS ,
205
+ Self :: Other ( other) => other. kind ( ) ,
206
+ }
207
+ }
208
+
209
+ fn emit_value ( & self , buffer : & mut [ u8 ] ) {
210
+ match self {
211
+ Self :: Unspecified => { }
212
+ Self :: Id ( id) => NetworkEndian :: write_u64 ( buffer, * id) ,
213
+ Self :: Destination ( ip) | Self :: Source ( ip) => {
214
+ buffer. copy_from_slice ( & ip. octets ( ) ) ;
215
+ }
216
+ Self :: Hoplimit ( value) | Self :: Tc ( value) => buffer[ 0 ] = * value,
217
+ Self :: Flags ( flags) => BigEndian :: write_u16 ( buffer, flags. bits ( ) ) ,
218
+ Self :: Other ( other) => other. emit_value ( buffer) ,
219
+ }
220
+ }
221
+ }
222
+
223
+ // should probably be in utils
224
+ fn parse_u64_be ( payload : & [ u8 ] ) -> Result < u64 , DecodeError > {
225
+ if payload. len ( ) != size_of :: < u64 > ( ) {
226
+ return Err ( format ! ( "invalid u64: {payload:?}" ) . into ( ) ) ;
227
+ }
228
+ Ok ( BigEndian :: read_u64 ( payload) )
229
+ }
230
+
231
+ impl < ' a , T > Parseable < NlaBuffer < & ' a T > > for RouteIp6Tunnel
232
+ where
233
+ T : AsRef < [ u8 ] > + ?Sized ,
234
+ {
235
+ fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
236
+ let payload = buf. value ( ) ;
237
+ Ok ( match buf. kind ( ) {
238
+ LWTUNNEL_IP6_UNSPEC => Self :: Unspecified ,
239
+ LWTUNNEL_IP6_ID => Self :: Id (
240
+ parse_u64_be ( payload)
241
+ . context ( "invalid LWTUNNEL_IP6_ID value" ) ?,
242
+ ) ,
243
+ LWTUNNEL_IP6_DST => Self :: Destination (
244
+ parse_ipv6_addr ( payload)
245
+ . context ( "invalid LWTUNNEL_IP6_DST value" ) ?,
246
+ ) ,
247
+ LWTUNNEL_IP6_SRC => Self :: Source (
248
+ parse_ipv6_addr ( payload)
249
+ . context ( "invalid LWTUNNEL_IP6_SRC value" ) ?,
250
+ ) ,
251
+ LWTUNNEL_IP6_HOPLIMIT => Self :: Hoplimit (
252
+ parse_u8 ( payload)
253
+ . context ( "invalid LWTUNNEL_IP6_HOPLIMIT value" ) ?,
254
+ ) ,
255
+ LWTUNNEL_IP6_TC => Self :: Tc (
256
+ parse_u8 ( payload) . context ( "invalid LWTUNNEL_IP6_TC value" ) ?,
257
+ ) ,
258
+ LWTUNNEL_IP6_FLAGS => {
259
+ Self :: Flags ( RouteIp6TunnelFlags :: from_bits_retain (
260
+ parse_u16_be ( payload)
261
+ . context ( "invalid LWTUNNEL_IP6_FLAGS value" ) ?,
262
+ ) )
263
+ }
264
+ _ => Self :: Other ( DefaultNla :: parse ( buf) ?) ,
265
+ } )
266
+ }
267
+ }
268
+
109
269
#[ derive( Debug , PartialEq , Eq , Clone ) ]
110
270
#[ non_exhaustive]
111
271
pub enum RouteLwTunnelEncap {
112
272
Mpls ( RouteMplsIpTunnel ) ,
113
273
Seg6 ( RouteSeg6IpTunnel ) ,
274
+ Ip6 ( RouteIp6Tunnel ) ,
114
275
Other ( DefaultNla ) ,
115
276
}
116
277
@@ -119,6 +280,7 @@ impl Nla for RouteLwTunnelEncap {
119
280
match self {
120
281
Self :: Mpls ( v) => v. value_len ( ) ,
121
282
Self :: Seg6 ( v) => v. value_len ( ) ,
283
+ Self :: Ip6 ( v) => v. value_len ( ) ,
122
284
Self :: Other ( v) => v. value_len ( ) ,
123
285
}
124
286
}
@@ -127,6 +289,7 @@ impl Nla for RouteLwTunnelEncap {
127
289
match self {
128
290
Self :: Mpls ( v) => v. emit_value ( buffer) ,
129
291
Self :: Seg6 ( v) => v. emit_value ( buffer) ,
292
+ Self :: Ip6 ( v) => v. emit_value ( buffer) ,
130
293
Self :: Other ( v) => v. emit_value ( buffer) ,
131
294
}
132
295
}
@@ -135,6 +298,7 @@ impl Nla for RouteLwTunnelEncap {
135
298
match self {
136
299
Self :: Mpls ( v) => v. kind ( ) ,
137
300
Self :: Seg6 ( v) => v. kind ( ) ,
301
+ Self :: Ip6 ( v) => v. kind ( ) ,
138
302
Self :: Other ( v) => v. kind ( ) ,
139
303
}
140
304
}
@@ -156,6 +320,7 @@ where
156
320
RouteLwEnCapType :: Seg6 => {
157
321
Self :: Seg6 ( RouteSeg6IpTunnel :: parse ( buf) ?)
158
322
}
323
+ RouteLwEnCapType :: Ip6 => Self :: Ip6 ( RouteIp6Tunnel :: parse ( buf) ?) ,
159
324
_ => Self :: Other ( DefaultNla :: parse ( buf) ?) ,
160
325
} )
161
326
}
0 commit comments