33use anyhow:: Context ;
44use byteorder:: { ByteOrder , NativeEndian } ;
55use netlink_packet_utils:: {
6- nla:: { self , DefaultNla , NlaBuffer } ,
7- parsers:: parse_u16,
6+ nla:: { DefaultNla , Nla , NlaBuffer , NlasIterator } ,
7+ parsers:: { parse_u16, parse_u32 } ,
88 traits:: Parseable ,
9- DecodeError ,
9+ DecodeError , Emitable ,
1010} ;
1111
1212const IFLA_BRIDGE_FLAGS : u16 = 0 ;
13+ const IFLA_BRIDGE_MODE : u16 = 1 ;
1314const 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;
1419
1520#[ derive( Clone , Eq , PartialEq , Debug ) ]
1621#[ non_exhaustive]
1722pub enum AfSpecBridge {
18- Flags ( u16 ) ,
23+ Flags ( BridgeFlag ) ,
24+ Mode ( BridgeMode ) ,
1925 VlanInfo ( BridgeVlanInfo ) ,
26+ VlanTunnelInfo ( Vec < BridgeVlanTunnelInfo > ) ,
2027 Other ( DefaultNla ) ,
2128}
2229
23- impl nla :: Nla for AfSpecBridge {
30+ impl Nla for AfSpecBridge {
2431 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 ( ) ,
3038 }
3139 }
3240
3341 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) => {
3850 buffer[ ..4 ] . copy_from_slice ( <[ u8 ; 4 ] >:: from ( info) . as_slice ( ) )
3951 }
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) ,
4154 }
4255 }
4356
4457 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 ( ) ,
5064 }
5165 }
5266}
5367
5468impl < ' a , T : AsRef < [ u8 ] > + ?Sized > Parseable < NlaBuffer < & ' a T > > for AfSpecBridge {
5569 fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
56- use self :: AfSpecBridge :: * ;
57-
5870 let payload = buf. value ( ) ;
5971 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 ( ) ,
6376 ) ,
64- IFLA_BRIDGE_FLAGS => Flags (
77+ IFLA_BRIDGE_MODE => Self :: Mode (
6578 parse_u16 ( payload)
66- . context ( "invalid IFLA_BRIDGE_FLAGS value" ) ?,
79+ . context ( "Invalid IFLA_BRIDGE_MODE value" ) ?
80+ . into ( ) ,
6781 ) ,
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 (
6998 DefaultNla :: parse ( buf)
7099 . context ( format ! ( "Unknown NLA type {kind}" ) ) ?,
71100 ) ,
@@ -83,27 +112,62 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
83112 fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
84113 let mut nlas = vec ! [ ] ;
85114 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 ( ) ) {
89116 let nla = nla. context ( err) ?;
90117 nlas. push ( AfSpecBridge :: parse ( & nla) . context ( err) ?) ;
91118 }
92119 Ok ( Self ( nlas) )
93120 }
94121}
95122
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 ) ]
98158pub struct BridgeVlanInfo {
99- pub flags : u16 ,
159+ pub flags : BridgeVlanInfoFlags ,
100160 pub vid : u16 ,
101161}
102162
163+ impl BridgeVlanInfo {
164+ pub const LENGTH : usize = 4 ;
165+ }
166+
103167impl From < & BridgeVlanInfo > for [ u8 ; 4 ] {
104168 fn from ( d : & BridgeVlanInfo ) -> Self {
105169 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 ( ) ) ;
107171 NativeEndian :: write_u16 ( & mut ret[ 2 ..4 ] , d. vid ) ;
108172 ret
109173 }
@@ -114,9 +178,11 @@ impl TryFrom<&[u8]> for BridgeVlanInfo {
114178 fn try_from ( raw : & [ u8 ] ) -> Result < Self , DecodeError > {
115179 if raw. len ( ) == 4 {
116180 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+ ) ,
120186 vid : parse_u16 ( & raw [ 2 ..4 ] ) . context ( format ! (
121187 "Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
122188 ) ) ?,
@@ -129,3 +195,150 @@ impl TryFrom<&[u8]> for BridgeVlanInfo {
129195 }
130196 }
131197}
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