@@ -944,8 +944,8 @@ pub enum InfoVlan {
944944 Unspec ( Vec < u8 > ) ,
945945 Id ( u16 ) ,
946946 Flags ( ( u32 , u32 ) ) ,
947- EgressQos ( Vec < u8 > ) ,
948- IngressQos ( Vec < u8 > ) ,
947+ EgressQos ( Vec < VlanQosMapping > ) ,
948+ IngressQos ( Vec < VlanQosMapping > ) ,
949949 Protocol ( u16 ) ,
950950}
951951
@@ -956,10 +956,10 @@ impl Nla for InfoVlan {
956956 match self {
957957 Id ( _) | Protocol ( _) => 2 ,
958958 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 ( ) ,
963963 }
964964 }
965965
@@ -968,10 +968,9 @@ impl Nla for InfoVlan {
968968 use self :: InfoVlan :: * ;
969969 match self {
970970 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) ,
975974 Id ( ref value)
976975 | Protocol ( ref value)
977976 => NativeEndian :: write_u16 ( buffer, * value) ,
@@ -996,6 +995,16 @@ impl Nla for InfoVlan {
996995 }
997996}
998997
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+
9991008impl < ' a , T : AsRef < [ u8 ] > + ?Sized > Parseable < NlaBuffer < & ' a T > > for InfoVlan {
10001009 fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
10011010 use self :: InfoVlan :: * ;
@@ -1014,8 +1023,14 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVlan {
10141023 let mask = parse_u32 ( & payload[ 4 ..] ) . context ( err) ?;
10151024 Flags ( ( flags, mask) )
10161025 }
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+ ) ,
10191034 IFLA_VLAN_PROTOCOL => Protocol (
10201035 parse_u16_be ( payload)
10211036 . context ( "invalid IFLA_VLAN_PROTOCOL value" ) ?,
@@ -1522,6 +1537,66 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacVtap {
15221537 }
15231538}
15241539
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+
15251600#[ cfg( test) ]
15261601mod tests {
15271602 use super :: * ;
@@ -2199,4 +2274,73 @@ mod tests {
21992274 nlas. as_slice ( ) . emit ( & mut vec) ;
22002275 assert_eq ! ( & vec[ ..] , & BRIDGE [ ..] ) ;
22012276 }
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+ }
22022346}
0 commit comments