3
3
use anyhow:: Context ;
4
4
use byteorder:: { ByteOrder , NativeEndian } ;
5
5
use netlink_packet_utils:: {
6
- nla:: { self , DefaultNla , NlaBuffer } ,
7
- parsers:: parse_u16,
6
+ nla:: { DefaultNla , Nla , NlaBuffer , NlasIterator } ,
7
+ parsers:: { parse_u16, parse_u32 } ,
8
8
traits:: Parseable ,
9
- DecodeError ,
9
+ DecodeError , Emitable ,
10
10
} ;
11
11
12
12
const IFLA_BRIDGE_FLAGS : u16 = 0 ;
13
+ const IFLA_BRIDGE_MODE : u16 = 1 ;
13
14
const IFLA_BRIDGE_VLAN_INFO : u16 = 2 ;
15
+ const IFLA_BRIDGE_VLAN_TUNNEL_INFO : u16 = 3 ;
16
+ // const IFLA_BRIDGE_MRP: u16 = 4;
17
+ // const IFLA_BRIDGE_CFM: u16 = 5;
18
+ // const IFLA_BRIDGE_MST: u16 = 6;
14
19
15
20
#[ derive( Clone , Eq , PartialEq , Debug ) ]
16
21
#[ non_exhaustive]
17
22
pub enum AfSpecBridge {
18
- Flags ( u16 ) ,
23
+ Flags ( BridgeFlag ) ,
24
+ Mode ( BridgeMode ) ,
19
25
VlanInfo ( BridgeVlanInfo ) ,
26
+ VlanTunnelInfo ( Vec < BridgeVlanTunnelInfo > ) ,
20
27
Other ( DefaultNla ) ,
21
28
}
22
29
23
- impl nla :: Nla for AfSpecBridge {
30
+ impl Nla for AfSpecBridge {
24
31
fn value_len ( & self ) -> usize {
25
- use self :: AfSpecBridge :: * ;
26
- match * self {
27
- VlanInfo ( _) => 4 ,
28
- Flags ( _) => 2 ,
29
- Other ( ref nla) => nla. value_len ( ) ,
32
+ match self {
33
+ Self :: Flags ( _) => BridgeFlag :: LENGTH ,
34
+ Self :: Mode ( _) => BridgeMode :: LENGTH ,
35
+ Self :: VlanInfo ( _) => BridgeVlanInfo :: LENGTH ,
36
+ Self :: VlanTunnelInfo ( s) => s. as_slice ( ) . buffer_len ( ) ,
37
+ Self :: Other ( nla) => nla. value_len ( ) ,
30
38
}
31
39
}
32
40
33
41
fn emit_value ( & self , buffer : & mut [ u8 ] ) {
34
- use self :: AfSpecBridge :: * ;
35
- match * self {
36
- Flags ( value) => NativeEndian :: write_u16 ( buffer, value) ,
37
- VlanInfo ( ref info) => {
42
+ match self {
43
+ Self :: Flags ( value) => {
44
+ NativeEndian :: write_u16 ( buffer, u16:: from ( * value) )
45
+ }
46
+ Self :: Mode ( value) => {
47
+ NativeEndian :: write_u16 ( buffer, u16:: from ( * value) )
48
+ }
49
+ Self :: VlanInfo ( info) => {
38
50
buffer[ ..4 ] . copy_from_slice ( <[ u8 ; 4 ] >:: from ( info) . as_slice ( ) )
39
51
}
40
- Other ( ref nla) => nla. emit_value ( buffer) ,
52
+ Self :: VlanTunnelInfo ( s) => s. as_slice ( ) . emit ( buffer) ,
53
+ Self :: Other ( nla) => nla. emit_value ( buffer) ,
41
54
}
42
55
}
43
56
44
57
fn kind ( & self ) -> u16 {
45
- use self :: AfSpecBridge :: * ;
46
- match * self {
47
- Flags ( _) => IFLA_BRIDGE_FLAGS ,
48
- VlanInfo ( _) => IFLA_BRIDGE_VLAN_INFO ,
49
- Other ( ref nla) => nla. kind ( ) ,
58
+ match self {
59
+ Self :: Flags ( _) => IFLA_BRIDGE_FLAGS ,
60
+ Self :: Mode ( _) => IFLA_BRIDGE_MODE ,
61
+ Self :: VlanInfo ( _) => IFLA_BRIDGE_VLAN_INFO ,
62
+ Self :: VlanTunnelInfo ( _) => IFLA_BRIDGE_VLAN_TUNNEL_INFO ,
63
+ Self :: Other ( nla) => nla. kind ( ) ,
50
64
}
51
65
}
52
66
}
53
67
54
68
impl < ' a , T : AsRef < [ u8 ] > + ?Sized > Parseable < NlaBuffer < & ' a T > > for AfSpecBridge {
55
69
fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
56
- use self :: AfSpecBridge :: * ;
57
-
58
70
let payload = buf. value ( ) ;
59
71
Ok ( match buf. kind ( ) {
60
- IFLA_BRIDGE_VLAN_INFO => VlanInfo (
61
- BridgeVlanInfo :: try_from ( payload)
62
- . context ( "Invalid IFLA_BRIDGE_VLAN_INFO value" ) ?,
72
+ IFLA_BRIDGE_FLAGS => Self :: Flags (
73
+ parse_u16 ( payload)
74
+ . context ( "Invalid IFLA_BRIDGE_FLAGS value" ) ?
75
+ . into ( ) ,
63
76
) ,
64
- IFLA_BRIDGE_FLAGS => Flags (
77
+ IFLA_BRIDGE_MODE => Self :: Mode (
65
78
parse_u16 ( payload)
66
- . context ( "invalid IFLA_BRIDGE_FLAGS value" ) ?,
79
+ . context ( "Invalid IFLA_BRIDGE_MODE value" ) ?
80
+ . into ( ) ,
67
81
) ,
68
- kind => Other (
82
+ IFLA_BRIDGE_VLAN_INFO => Self :: VlanInfo (
83
+ BridgeVlanInfo :: try_from ( payload)
84
+ . context ( "Invalid IFLA_BRIDGE_VLAN_INFO value" ) ?,
85
+ ) ,
86
+ IFLA_BRIDGE_VLAN_TUNNEL_INFO => {
87
+ let mut nlas = Vec :: new ( ) ;
88
+ for nla in NlasIterator :: new ( payload) {
89
+ let nla = & nla. context ( format ! (
90
+ "Invalid IFLA_BRIDGE_VLAN_TUNNEL_INFO for {payload:?}"
91
+ ) ) ?;
92
+ let parsed = BridgeVlanTunnelInfo :: parse ( nla) ?;
93
+ nlas. push ( parsed) ;
94
+ }
95
+ Self :: VlanTunnelInfo ( nlas)
96
+ }
97
+ kind => Self :: Other (
69
98
DefaultNla :: parse ( buf)
70
99
. context ( format ! ( "Unknown NLA type {kind}" ) ) ?,
71
100
) ,
@@ -83,27 +112,62 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
83
112
fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
84
113
let mut nlas = vec ! [ ] ;
85
114
let err = "Invalid AF_INET NLA for IFLA_AF_SPEC(AF_BRIDGE)" ;
86
- for nla in
87
- netlink_packet_utils:: nla:: NlasIterator :: new ( buf. into_inner ( ) )
88
- {
115
+ for nla in NlasIterator :: new ( buf. into_inner ( ) ) {
89
116
let nla = nla. context ( err) ?;
90
117
nlas. push ( AfSpecBridge :: parse ( & nla) . context ( err) ?) ;
91
118
}
92
119
Ok ( Self ( nlas) )
93
120
}
94
121
}
95
122
96
- #[ derive( Debug , PartialEq , Eq , Clone , Copy , Default ) ]
97
- #[ non_exhaustive]
123
+ const BRIDGE_VLAN_INFO_CONTROLLER : u16 = 1 << 0 ;
124
+ const BRIDGE_VLAN_INFO_PVID : u16 = 1 << 1 ;
125
+ const BRIDGE_VLAN_INFO_UNTAGGED : u16 = 1 << 2 ;
126
+ const BRIDGE_VLAN_INFO_RANGE_BEGIN : u16 = 1 << 3 ;
127
+ const BRIDGE_VLAN_INFO_RANGE_END : u16 = 1 << 4 ;
128
+ const BRIDGE_VLAN_INFO_BRENTRY : u16 = 1 << 5 ;
129
+ const BRIDGE_VLAN_INFO_ONLY_OPTS : u16 = 1 << 6 ;
130
+
131
+ bitflags ! {
132
+ #[ non_exhaustive]
133
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
134
+ pub struct BridgeVlanInfoFlags : u16 {
135
+ /// Operate on Bridge device as well
136
+ const Controller = BRIDGE_VLAN_INFO_CONTROLLER ;
137
+ /// VLAN is PVID, ingress untagged
138
+ const Pvid = BRIDGE_VLAN_INFO_PVID ;
139
+ /// VLAN egresses untagged
140
+ const Untagged = BRIDGE_VLAN_INFO_UNTAGGED ;
141
+ /// VLAN is start of vlan range
142
+ const RangeBegin = BRIDGE_VLAN_INFO_RANGE_BEGIN ;
143
+ /// VLAN is end of vlan range
144
+ const RangeEnd = BRIDGE_VLAN_INFO_RANGE_END ;
145
+ /// Global bridge VLAN entry
146
+ const Brentry = BRIDGE_VLAN_INFO_BRENTRY ;
147
+ /// Skip create/delete/flags
148
+ const OnlyOpts = BRIDGE_VLAN_INFO_ONLY_OPTS ;
149
+ const _ = !0 ;
150
+ }
151
+ }
152
+
153
+ impl BridgeVlanInfoFlags {
154
+ pub const LENGTH : usize = 2 ;
155
+ }
156
+
157
+ #[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
98
158
pub struct BridgeVlanInfo {
99
- pub flags : u16 ,
159
+ pub flags : BridgeVlanInfoFlags ,
100
160
pub vid : u16 ,
101
161
}
102
162
163
+ impl BridgeVlanInfo {
164
+ pub const LENGTH : usize = 4 ;
165
+ }
166
+
103
167
impl From < & BridgeVlanInfo > for [ u8 ; 4 ] {
104
168
fn from ( d : & BridgeVlanInfo ) -> Self {
105
169
let mut ret = [ 0u8 ; 4 ] ;
106
- NativeEndian :: write_u16 ( & mut ret[ 0 ..2 ] , d. flags ) ;
170
+ NativeEndian :: write_u16 ( & mut ret[ 0 ..2 ] , d. flags . bits ( ) ) ;
107
171
NativeEndian :: write_u16 ( & mut ret[ 2 ..4 ] , d. vid ) ;
108
172
ret
109
173
}
@@ -114,9 +178,11 @@ impl TryFrom<&[u8]> for BridgeVlanInfo {
114
178
fn try_from ( raw : & [ u8 ] ) -> Result < Self , DecodeError > {
115
179
if raw. len ( ) == 4 {
116
180
Ok ( Self {
117
- flags : parse_u16 ( & raw [ 0 ..2 ] ) . context ( format ! (
118
- "Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
119
- ) ) ?,
181
+ flags : BridgeVlanInfoFlags :: from_bits_retain (
182
+ parse_u16 ( & raw [ 0 ..2 ] ) . context ( format ! (
183
+ "Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
184
+ ) ) ?,
185
+ ) ,
120
186
vid : parse_u16 ( & raw [ 2 ..4 ] ) . context ( format ! (
121
187
"Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
122
188
) ) ?,
@@ -129,3 +195,150 @@ impl TryFrom<&[u8]> for BridgeVlanInfo {
129
195
}
130
196
}
131
197
}
198
+
199
+ // kernel constant name is BRIDGE_FLAGS_MASTER
200
+ const BRIDGE_FLAGS_CONTROLLER : u16 = 1 ;
201
+ const BRIDGE_FLAGS_SELF : u16 = 2 ;
202
+
203
+ #[ derive( Clone , Copy , Eq , PartialEq , Debug ) ]
204
+ #[ non_exhaustive]
205
+ pub enum BridgeFlag {
206
+ /// Bridge command to/from controller
207
+ Controller ,
208
+ /// Bridge command to/from lowerdev
209
+ LowerDev ,
210
+ Other ( u16 ) ,
211
+ }
212
+
213
+ impl From < u16 > for BridgeFlag {
214
+ fn from ( d : u16 ) -> Self {
215
+ match d {
216
+ BRIDGE_FLAGS_CONTROLLER => Self :: Controller ,
217
+ BRIDGE_FLAGS_SELF => Self :: LowerDev ,
218
+ _ => Self :: Other ( d) ,
219
+ }
220
+ }
221
+ }
222
+
223
+ impl From < BridgeFlag > for u16 {
224
+ fn from ( v : BridgeFlag ) -> u16 {
225
+ match v {
226
+ BridgeFlag :: Controller => BRIDGE_FLAGS_CONTROLLER ,
227
+ BridgeFlag :: LowerDev => BRIDGE_FLAGS_SELF ,
228
+ BridgeFlag :: Other ( d) => d,
229
+ }
230
+ }
231
+ }
232
+
233
+ impl BridgeFlag {
234
+ pub const LENGTH : usize = 2 ;
235
+ }
236
+
237
+ const BRIDGE_MODE_VEB : u16 = 0 ;
238
+ const BRIDGE_MODE_VEPA : u16 = 1 ;
239
+
240
+ #[ derive( Clone , Copy , Eq , PartialEq , Debug ) ]
241
+ #[ non_exhaustive]
242
+ pub enum BridgeMode {
243
+ /// Default loopback mode
244
+ Veb ,
245
+ /// 802.1Qbg defined VEPA mode
246
+ Vepa ,
247
+ Other ( u16 ) ,
248
+ }
249
+
250
+ impl From < u16 > for BridgeMode {
251
+ fn from ( d : u16 ) -> Self {
252
+ match d {
253
+ BRIDGE_MODE_VEB => Self :: Veb ,
254
+ BRIDGE_MODE_VEPA => Self :: Vepa ,
255
+ _ => Self :: Other ( d) ,
256
+ }
257
+ }
258
+ }
259
+
260
+ impl From < BridgeMode > for u16 {
261
+ fn from ( v : BridgeMode ) -> u16 {
262
+ match v {
263
+ BridgeMode :: Veb => BRIDGE_MODE_VEB ,
264
+ BridgeMode :: Vepa => BRIDGE_MODE_VEPA ,
265
+ BridgeMode :: Other ( d) => d,
266
+ }
267
+ }
268
+ }
269
+
270
+ impl BridgeMode {
271
+ pub const LENGTH : usize = 2 ;
272
+ }
273
+
274
+ const IFLA_BRIDGE_VLAN_TUNNEL_ID : u16 = 1 ;
275
+ const IFLA_BRIDGE_VLAN_TUNNEL_VID : u16 = 2 ;
276
+ const IFLA_BRIDGE_VLAN_TUNNEL_FLAGS : u16 = 3 ;
277
+
278
+ #[ derive( Clone , Eq , PartialEq , Debug ) ]
279
+ #[ non_exhaustive]
280
+ pub enum BridgeVlanTunnelInfo {
281
+ Id ( u32 ) ,
282
+ Vid ( u16 ) ,
283
+ Flags ( BridgeVlanInfoFlags ) ,
284
+ Other ( DefaultNla ) ,
285
+ }
286
+
287
+ impl Nla for BridgeVlanTunnelInfo {
288
+ fn value_len ( & self ) -> usize {
289
+ match self {
290
+ Self :: Id ( _) => 4 ,
291
+ Self :: Vid ( _) => 2 ,
292
+ Self :: Flags ( _) => BridgeVlanInfoFlags :: LENGTH ,
293
+ Self :: Other ( nla) => nla. value_len ( ) ,
294
+ }
295
+ }
296
+
297
+ fn emit_value ( & self , buffer : & mut [ u8 ] ) {
298
+ match self {
299
+ Self :: Id ( v) => NativeEndian :: write_u32 ( buffer, * v) ,
300
+ Self :: Vid ( v) => NativeEndian :: write_u16 ( buffer, * v) ,
301
+ Self :: Flags ( value) => NativeEndian :: write_u16 ( buffer, value. bits ( ) ) ,
302
+ Self :: Other ( nla) => nla. emit_value ( buffer) ,
303
+ }
304
+ }
305
+
306
+ fn kind ( & self ) -> u16 {
307
+ match self {
308
+ Self :: Id ( _) => IFLA_BRIDGE_VLAN_TUNNEL_ID ,
309
+ Self :: Vid ( _) => IFLA_BRIDGE_VLAN_TUNNEL_VID ,
310
+ Self :: Flags ( _) => IFLA_BRIDGE_VLAN_TUNNEL_FLAGS ,
311
+ Self :: Other ( nla) => nla. kind ( ) ,
312
+ }
313
+ }
314
+ }
315
+
316
+ impl < ' a , T : AsRef < [ u8 ] > + ?Sized > Parseable < NlaBuffer < & ' a T > >
317
+ for BridgeVlanTunnelInfo
318
+ {
319
+ fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
320
+ let payload = buf. value ( ) ;
321
+ Ok ( match buf. kind ( ) {
322
+ IFLA_BRIDGE_VLAN_TUNNEL_ID => {
323
+ Self :: Id ( parse_u32 ( payload) . context ( format ! (
324
+ "Invalid IFLA_BRIDGE_VLAN_TUNNEL_ID {payload:?}"
325
+ ) ) ?)
326
+ }
327
+ IFLA_BRIDGE_VLAN_TUNNEL_VID => {
328
+ Self :: Vid ( parse_u16 ( payload) . context ( format ! (
329
+ "Invalid IFLA_BRIDGE_VLAN_TUNNEL_VID {payload:?}"
330
+ ) ) ?)
331
+ }
332
+ IFLA_BRIDGE_VLAN_TUNNEL_FLAGS => {
333
+ Self :: Flags ( BridgeVlanInfoFlags :: from_bits_retain (
334
+ parse_u16 ( payload) . context ( format ! (
335
+ "Invalid IFLA_BRIDGE_VLAN_TUNNEL_VID {payload:?}"
336
+ ) ) ?,
337
+ ) )
338
+ }
339
+ _ => {
340
+ Self :: Other ( DefaultNla :: parse ( buf) . context ( "Unknown NLA type" ) ?)
341
+ }
342
+ } )
343
+ }
344
+ }
0 commit comments