@@ -944,8 +944,8 @@ pub enum InfoVlan {
944
944
Unspec ( Vec < u8 > ) ,
945
945
Id ( u16 ) ,
946
946
Flags ( ( u32 , u32 ) ) ,
947
- EgressQos ( Vec < u8 > ) ,
948
- IngressQos ( Vec < u8 > ) ,
947
+ EgressQos ( Vec < VlanQosMapping > ) ,
948
+ IngressQos ( Vec < VlanQosMapping > ) ,
949
949
Protocol ( u16 ) ,
950
950
}
951
951
@@ -956,10 +956,10 @@ impl Nla for InfoVlan {
956
956
match self {
957
957
Id ( _) | Protocol ( _) => 2 ,
958
958
Flags ( _) => 8 ,
959
- Unspec ( bytes)
960
- | EgressQos ( bytes )
961
- | IngressQos ( bytes )
962
- => bytes . len ( ) ,
959
+ Unspec ( bytes) => bytes . len ( ) ,
960
+ EgressQos ( mappings )
961
+ | IngressQos ( mappings )
962
+ => mappings . as_slice ( ) . buffer_len ( ) ,
963
963
}
964
964
}
965
965
@@ -968,10 +968,9 @@ impl Nla for InfoVlan {
968
968
use self :: InfoVlan :: * ;
969
969
match self {
970
970
Unspec ( ref bytes)
971
- | EgressQos ( ref bytes)
972
- | IngressQos ( ref bytes)
973
- => buffer. copy_from_slice ( bytes) ,
974
-
971
+ => buffer. copy_from_slice ( bytes) ,
972
+ EgressQos ( ref mappings)
973
+ | IngressQos ( ref mappings) => mappings. as_slice ( ) . emit ( buffer) ,
975
974
Id ( ref value)
976
975
| Protocol ( ref value)
977
976
=> NativeEndian :: write_u16 ( buffer, * value) ,
@@ -996,6 +995,16 @@ impl Nla for InfoVlan {
996
995
}
997
996
}
998
997
998
+ fn parse_mappings ( payload : & [ u8 ] ) -> Result < Vec < VlanQosMapping > , DecodeError > {
999
+ let mut mappings = Vec :: new ( ) ;
1000
+ for nla in NlasIterator :: new ( payload) {
1001
+ let nla = nla?;
1002
+ let parsed = VlanQosMapping :: parse ( & nla) ?;
1003
+ mappings. push ( parsed) ;
1004
+ }
1005
+ Ok ( mappings)
1006
+ }
1007
+
999
1008
impl < ' a , T : AsRef < [ u8 ] > + ?Sized > Parseable < NlaBuffer < & ' a T > > for InfoVlan {
1000
1009
fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
1001
1010
use self :: InfoVlan :: * ;
@@ -1014,8 +1023,14 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVlan {
1014
1023
let mask = parse_u32 ( & payload[ 4 ..] ) . context ( err) ?;
1015
1024
Flags ( ( flags, mask) )
1016
1025
}
1017
- IFLA_VLAN_EGRESS_QOS => EgressQos ( payload. to_vec ( ) ) ,
1018
- IFLA_VLAN_INGRESS_QOS => IngressQos ( payload. to_vec ( ) ) ,
1026
+ IFLA_VLAN_EGRESS_QOS => EgressQos (
1027
+ parse_mappings ( payload)
1028
+ . context ( "failed to parse IFLA_VLAN_EGRESS_QOS" ) ?,
1029
+ ) ,
1030
+ IFLA_VLAN_INGRESS_QOS => IngressQos (
1031
+ parse_mappings ( payload)
1032
+ . context ( "failed to parse IFLA_VLAN_INGRESS_QOS" ) ?,
1033
+ ) ,
1019
1034
IFLA_VLAN_PROTOCOL => Protocol (
1020
1035
parse_u16_be ( payload)
1021
1036
. context ( "invalid IFLA_VLAN_PROTOCOL value" ) ?,
@@ -1522,6 +1537,66 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacVtap {
1522
1537
}
1523
1538
}
1524
1539
1540
+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
1541
+ #[ non_exhaustive]
1542
+ pub enum VlanQosMapping {
1543
+ Unspec ( Vec < u8 > ) ,
1544
+ Mapping { from : u32 , to : u32 } ,
1545
+ Other ( DefaultNla ) ,
1546
+ }
1547
+
1548
+ impl Nla for VlanQosMapping {
1549
+ fn value_len ( & self ) -> usize {
1550
+ match self {
1551
+ VlanQosMapping :: Unspec ( bytes) => bytes. len ( ) ,
1552
+ VlanQosMapping :: Mapping { .. } => 8 ,
1553
+ VlanQosMapping :: Other ( nla) => nla. value_len ( ) ,
1554
+ }
1555
+ }
1556
+
1557
+ fn kind ( & self ) -> u16 {
1558
+ match self {
1559
+ VlanQosMapping :: Unspec ( _) => IFLA_VLAN_QOS_UNSPEC ,
1560
+ VlanQosMapping :: Mapping { .. } => IFLA_VLAN_QOS_MAPPING ,
1561
+ VlanQosMapping :: Other ( nla) => nla. kind ( ) ,
1562
+ }
1563
+ }
1564
+
1565
+ fn emit_value ( & self , buffer : & mut [ u8 ] ) {
1566
+ use VlanQosMapping :: * ;
1567
+ match self {
1568
+ Unspec ( payload) => buffer. copy_from_slice ( payload) ,
1569
+ Mapping { from, to } => {
1570
+ NativeEndian :: write_u32 ( buffer, * from) ;
1571
+ NativeEndian :: write_u32 ( & mut buffer[ 4 ..] , * to) ;
1572
+ }
1573
+ Other ( nla) => nla. emit_value ( buffer) ,
1574
+ }
1575
+ }
1576
+ }
1577
+
1578
+ impl < ' a , T : AsRef < [ u8 ] > + ?Sized > Parseable < NlaBuffer < & ' a T > >
1579
+ for VlanQosMapping
1580
+ {
1581
+ fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
1582
+ use VlanQosMapping :: * ;
1583
+ let payload = buf. value ( ) ;
1584
+ Ok ( match buf. kind ( ) {
1585
+ IFLA_VLAN_QOS_UNSPEC => Unspec ( payload. to_vec ( ) ) ,
1586
+ IFLA_VLAN_QOS_MAPPING => Mapping {
1587
+ from : parse_u32 ( & payload[ ..4 ] )
1588
+ . context ( "expected u32 from value" ) ?,
1589
+ to : parse_u32 ( & payload[ 4 ..] )
1590
+ . context ( "expected u32 to value" ) ?,
1591
+ } ,
1592
+ kind => Other (
1593
+ DefaultNla :: parse ( buf)
1594
+ . context ( format ! ( "unknown NLA type {kind}" ) ) ?,
1595
+ ) ,
1596
+ } )
1597
+ }
1598
+ }
1599
+
1525
1600
#[ cfg( test) ]
1526
1601
mod tests {
1527
1602
use super :: * ;
@@ -2199,4 +2274,73 @@ mod tests {
2199
2274
nlas. as_slice ( ) . emit ( & mut vec) ;
2200
2275
assert_eq ! ( & vec[ ..] , & BRIDGE [ ..] ) ;
2201
2276
}
2277
+
2278
+ #[ rustfmt:: skip]
2279
+ static VLAN : [ u8 ; 68 ] = [
2280
+ 0x09 , 0x00 , // length = 9
2281
+ 0x01 , 0x00 , // type = 1 = IFLA_INFO_KIND
2282
+ 0x76 , 0x6c , 0x61 , 0x6e , 0x00 , // V = "vlan\0"
2283
+ 0x00 , 0x00 , 0x00 , // padding
2284
+ 0x38 , 0x00 , // length = 56
2285
+ 0x02 , 0x00 , // type = 2 = IFLA_INFO_DATA
2286
+ 0x06 , 0x00 , // length - 6
2287
+ 0x01 , 0x00 , // type = 1 = IFLA_VLAN_ID
2288
+ 0x4b , 0x00 , // id = 0x4b = 75
2289
+ 0x00 , 0x00 , // padding
2290
+ 0x10 , 0x00 , // length = 16
2291
+ 0x03 , 0x00 , // type = 3 = IFLA_VLAN_EGRESS_QOS_MAPPING
2292
+ 0x0c , 0x00 , // length = 12
2293
+ 0x01 , 0x00 , // type = 1 = IFLA_VLAN_QOS_MAPPING
2294
+ 0x03 , 0x00 , 0x00 , 0x00 , // from = 3
2295
+ 0x04 , 0x00 , 0x00 , 0x00 , // to = 4
2296
+ 0x1c , 0x00 , // length = 44
2297
+ 0x04 , 0x00 , // type = 4 = IFLA_VLAN_INGRESS_QOS_MAPPING
2298
+ 0x0c , 0x00 , // length = 12
2299
+ 0x01 , 0x00 , // type = 1 = IFLA_VLAN_QOS_MAPPING
2300
+ 0x00 , 0x00 , 0x00 , 0x00 , // from = 0
2301
+ 0x01 , 0x00 , 0x00 , 0x00 , // to = 1
2302
+ 0x0c , 0x00 , // length = 12
2303
+ 0x01 , 0x00 , // type = 1 = IFLA_VLAN_QOS_MAPPING
2304
+ 0x01 , 0x00 , 0x00 , 0x00 , // from = 1
2305
+ 0x02 , 0x00 , 0x00 , 0x00 , // to = 2
2306
+ ] ;
2307
+
2308
+ lazy_static ! {
2309
+ static ref VLAN_INFO : Vec <InfoVlan > = vec![
2310
+ InfoVlan :: Id ( 75 ) ,
2311
+ InfoVlan :: EgressQos ( vec![ VlanQosMapping :: Mapping {
2312
+ from: 3 ,
2313
+ to: 4
2314
+ } ] ) ,
2315
+ InfoVlan :: IngressQos ( vec![
2316
+ VlanQosMapping :: Mapping { from: 0 , to: 1 } ,
2317
+ VlanQosMapping :: Mapping { from: 1 , to: 2 }
2318
+ ] ) ,
2319
+ ] ;
2320
+ }
2321
+
2322
+ #[ test]
2323
+ fn parse_info_vlan ( ) {
2324
+ let nla = NlaBuffer :: new_checked ( & VLAN [ ..] ) . unwrap ( ) ;
2325
+ let parsed = VecInfo :: parse ( & nla) . unwrap ( ) . 0 ;
2326
+ let expected = vec ! [
2327
+ Info :: Kind ( InfoKind :: Vlan ) ,
2328
+ Info :: Data ( InfoData :: Vlan ( VLAN_INFO . clone( ) ) ) ,
2329
+ ] ;
2330
+ assert_eq ! ( expected, parsed) ;
2331
+ }
2332
+
2333
+ #[ test]
2334
+ fn emit_info_vlan ( ) {
2335
+ let nlas = vec ! [
2336
+ Info :: Kind ( InfoKind :: Vlan ) ,
2337
+ Info :: Data ( InfoData :: Vlan ( VLAN_INFO . clone( ) ) ) ,
2338
+ ] ;
2339
+
2340
+ assert_eq ! ( nlas. as_slice( ) . buffer_len( ) , VLAN . len( ) ) ;
2341
+
2342
+ let mut vec = vec ! [ 0xff ; VLAN . len( ) ] ;
2343
+ nlas. as_slice ( ) . emit ( & mut vec) ;
2344
+ assert_eq ! ( & vec[ ..] , & VLAN [ ..] ) ;
2345
+ }
2202
2346
}
0 commit comments