@@ -42,6 +42,7 @@ const IPOIB: &str = "ipoib";
4242const WIREGUARD : & str = "wireguard" ;
4343const XFRM : & str = "xfrm" ;
4444const MACSEC : & str = "macsec" ;
45+ const HSR : & str = "hsr" ;
4546
4647#[ derive( Debug , PartialEq , Eq , Clone ) ]
4748#[ non_exhaustive]
@@ -337,6 +338,17 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for VecInfo {
337338 }
338339 InfoData :: MacSec ( v)
339340 }
341+ InfoKind :: Hsr => {
342+ let mut v = Vec :: new ( ) ;
343+ let err = "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'hsr')" ;
344+ for nla in NlasIterator :: new ( payload) {
345+ let nla = & nla. context ( err) ?;
346+ let parsed =
347+ InfoHsr :: parse ( nla) . context ( err) ?;
348+ v. push ( parsed) ;
349+ }
350+ InfoData :: Hsr ( v)
351+ }
340352 } ;
341353 res. push ( Info :: Data ( info_data) ) ;
342354 } else {
@@ -383,6 +395,7 @@ pub enum InfoData {
383395 Wireguard ( Vec < u8 > ) ,
384396 Xfrm ( Vec < InfoXfrmTun > ) ,
385397 MacSec ( Vec < InfoMacSec > ) ,
398+ Hsr ( Vec < InfoHsr > ) ,
386399 Other ( Vec < u8 > ) ,
387400}
388401
@@ -403,6 +416,7 @@ impl Nla for InfoData {
403416 Vxlan ( ref nlas) => nlas. as_slice ( ) . buffer_len ( ) ,
404417 Xfrm ( ref nlas) => nlas. as_slice ( ) . buffer_len ( ) ,
405418 MacSec ( ref nlas) => nlas. as_slice ( ) . buffer_len ( ) ,
419+ Hsr ( ref nlas) => nlas. as_slice ( ) . buffer_len ( ) ,
406420 Dummy ( ref bytes)
407421 | Tun ( ref bytes)
408422 | Nlmon ( ref bytes)
@@ -437,6 +451,7 @@ impl Nla for InfoData {
437451 Vxlan ( ref nlas) => nlas. as_slice ( ) . emit ( buffer) ,
438452 Xfrm ( ref nlas) => nlas. as_slice ( ) . emit ( buffer) ,
439453 MacSec ( ref nlas) => nlas. as_slice ( ) . emit ( buffer) ,
454+ Hsr ( ref nlas) => nlas. as_slice ( ) . emit ( buffer) ,
440455 Dummy ( ref bytes)
441456 | Tun ( ref bytes)
442457 | Nlmon ( ref bytes)
@@ -519,6 +534,7 @@ pub enum InfoKind {
519534 Wireguard ,
520535 Xfrm ,
521536 MacSec ,
537+ Hsr ,
522538 Other ( String ) ,
523539}
524540
@@ -551,6 +567,7 @@ impl Nla for InfoKind {
551567 Wireguard => WIREGUARD . len ( ) ,
552568 Xfrm => XFRM . len ( ) ,
553569 MacSec => MACSEC . len ( ) ,
570+ Hsr => HSR . len ( ) ,
554571 Other ( ref s) => s. len ( ) ,
555572 } ;
556573 len + 1
@@ -584,6 +601,7 @@ impl Nla for InfoKind {
584601 Wireguard => WIREGUARD ,
585602 Xfrm => XFRM ,
586603 MacSec => MACSEC ,
604+ Hsr => HSR ,
587605 Other ( ref s) => s. as_str ( ) ,
588606 } ;
589607 buffer[ ..s. len ( ) ] . copy_from_slice ( s. as_bytes ( ) ) ;
@@ -633,6 +651,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoKind {
633651 WIREGUARD => Wireguard ,
634652 MACSEC => MacSec ,
635653 XFRM => Xfrm ,
654+ HSR => Hsr ,
636655 _ => Other ( s) ,
637656 } )
638657 }
@@ -1228,6 +1247,131 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacSec {
12281247 }
12291248}
12301249
1250+ #[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
1251+ #[ non_exhaustive]
1252+ pub enum HsrProtocol {
1253+ Hsr ,
1254+ Prp ,
1255+ Other ( u8 ) ,
1256+ }
1257+
1258+ impl From < u8 > for HsrProtocol {
1259+ fn from ( d : u8 ) -> Self {
1260+ match d {
1261+ HSR_PROTOCOL_HSR => Self :: Hsr ,
1262+ HSR_PROTOCOL_PRP => Self :: Prp ,
1263+ _ => Self :: Other ( d) ,
1264+ }
1265+ }
1266+ }
1267+
1268+ impl From < HsrProtocol > for u8 {
1269+ fn from ( d : HsrProtocol ) -> Self {
1270+ match d {
1271+ HsrProtocol :: Hsr => HSR_PROTOCOL_HSR ,
1272+ HsrProtocol :: Prp => HSR_PROTOCOL_PRP ,
1273+ HsrProtocol :: Other ( value) => value,
1274+ }
1275+ }
1276+ }
1277+
1278+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
1279+ #[ non_exhaustive]
1280+ pub enum InfoHsr {
1281+ Unspec ( Vec < u8 > ) ,
1282+ Port1 ( u32 ) ,
1283+ Port2 ( u32 ) ,
1284+ MulticastSpec ( u8 ) ,
1285+ SupervisionAddr ( [ u8 ; 6 ] ) ,
1286+ Version ( u8 ) ,
1287+ SeqNr ( u16 ) ,
1288+ Protocol ( HsrProtocol ) ,
1289+ Other ( DefaultNla ) ,
1290+ }
1291+
1292+ impl Nla for InfoHsr {
1293+ fn value_len ( & self ) -> usize {
1294+ use self :: InfoHsr :: * ;
1295+ match self {
1296+ Unspec ( bytes) => bytes. len ( ) ,
1297+ SupervisionAddr ( _) => 6 ,
1298+ Port1 ( _) | Port2 ( _) => 4 ,
1299+ SeqNr ( _) => 2 ,
1300+ MulticastSpec ( _) | Version ( _) | Protocol ( _) => 1 ,
1301+ Other ( nla) => nla. value_len ( ) ,
1302+ }
1303+ }
1304+
1305+ fn emit_value ( & self , buffer : & mut [ u8 ] ) {
1306+ use self :: InfoHsr :: * ;
1307+ match self {
1308+ Unspec ( bytes) => buffer. copy_from_slice ( bytes. as_slice ( ) ) ,
1309+ Port1 ( value) | Port2 ( value) => {
1310+ NativeEndian :: write_u32 ( buffer, * value)
1311+ }
1312+ MulticastSpec ( value) | Version ( value) => buffer[ 0 ] = * value,
1313+ SeqNr ( value) => NativeEndian :: write_u16 ( buffer, * value) ,
1314+ Protocol ( value) => buffer[ 0 ] = ( * value) . into ( ) ,
1315+ SupervisionAddr ( ref value) => buffer. copy_from_slice ( & value[ ..] ) ,
1316+ Other ( nla) => nla. emit_value ( buffer) ,
1317+ }
1318+ }
1319+
1320+ fn kind ( & self ) -> u16 {
1321+ use self :: InfoHsr :: * ;
1322+ match self {
1323+ Unspec ( _) => IFLA_HSR_UNSPEC ,
1324+ Port1 ( _) => IFLA_HSR_SLAVE1 ,
1325+ Port2 ( _) => IFLA_HSR_SLAVE2 ,
1326+ MulticastSpec ( _) => IFLA_HSR_MULTICAST_SPEC ,
1327+ SupervisionAddr ( _) => IFLA_HSR_SUPERVISION_ADDR ,
1328+ SeqNr ( _) => IFLA_HSR_SEQ_NR ,
1329+ Version ( _) => IFLA_HSR_VERSION ,
1330+ Protocol ( _) => IFLA_HSR_PROTOCOL ,
1331+ Other ( nla) => nla. kind ( ) ,
1332+ }
1333+ }
1334+ }
1335+
1336+ impl < ' a , T : AsRef < [ u8 ] > + ?Sized > Parseable < NlaBuffer < & ' a T > > for InfoHsr {
1337+ fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
1338+ use self :: InfoHsr :: * ;
1339+ let payload = buf. value ( ) ;
1340+ Ok ( match buf. kind ( ) {
1341+ IFLA_HSR_UNSPEC => Unspec ( payload. to_vec ( ) ) ,
1342+ IFLA_HSR_SLAVE1 => Port1 (
1343+ parse_u32 ( payload) . context ( "invalid IFLA_HSR_SLAVE1 value" ) ?,
1344+ ) ,
1345+ IFLA_HSR_SLAVE2 => Port2 (
1346+ parse_u32 ( payload) . context ( "invalid IFLA_HSR_SLAVE2 value" ) ?,
1347+ ) ,
1348+ IFLA_HSR_MULTICAST_SPEC => MulticastSpec (
1349+ parse_u8 ( payload)
1350+ . context ( "invalid IFLA_HSR_MULTICAST_SPEC value" ) ?,
1351+ ) ,
1352+ IFLA_HSR_SUPERVISION_ADDR => SupervisionAddr (
1353+ parse_mac ( payload)
1354+ . context ( "invalid IFLA_HSR_SUPERVISION_ADDR value" ) ?,
1355+ ) ,
1356+ IFLA_HSR_SEQ_NR => SeqNr (
1357+ parse_u16 ( payload) . context ( "invalid IFLA_HSR_SEQ_NR value" ) ?,
1358+ ) ,
1359+ IFLA_HSR_VERSION => Version (
1360+ parse_u8 ( payload) . context ( "invalid IFLA_HSR_VERSION value" ) ?,
1361+ ) ,
1362+ IFLA_HSR_PROTOCOL => Protocol (
1363+ parse_u8 ( payload)
1364+ . context ( "invalid IFLA_HSR_PROTOCOL value" ) ?
1365+ . into ( ) ,
1366+ ) ,
1367+ kind => Other (
1368+ DefaultNla :: parse ( buf)
1369+ . context ( format ! ( "unknown NLA type {kind}" ) ) ?,
1370+ ) ,
1371+ } )
1372+ }
1373+ }
1374+
12311375#[ derive( Debug , PartialEq , Eq , Clone ) ]
12321376#[ non_exhaustive]
12331377pub enum InfoXfrmTun {
@@ -2674,4 +2818,72 @@ mod tests {
26742818 nlas. as_slice ( ) . emit ( & mut vec) ;
26752819 assert_eq ! ( & vec[ ..] , & MACSEC [ ..] ) ;
26762820 }
2821+
2822+ #[ rustfmt:: skip]
2823+ static HSR : [ u8 ; 56 ] = [
2824+ 0x08 , 0x00 , // L = 8
2825+ 0x01 , 0x00 , // T = 1 (IFLA_INFO_KIND)
2826+ 0x68 , 0x73 , 0x72 , 0x00 , // V = "hsr"
2827+
2828+ 0x30 , 0x00 , // L = 48
2829+ 0x02 , 0x00 , // T = 2 (IFLA_INFO_DATA)
2830+
2831+ 0x08 , 0x00 , // L = 8
2832+ 0x01 , 0x00 , // T = 1 (IFLA_HSR_SLAVE1)
2833+ 0x18 , 0x00 , 0x00 , 0x00 , // V = 24
2834+
2835+ 0x08 , 0x00 , // L = 8
2836+ 0x02 , 0x00 , // T = 2 (IFLA_HSR_SLAVE2)
2837+ 0x1a , 0x00 , 0x00 , 0x00 , // V = 26
2838+
2839+ 0x0a , 0x00 , // L = 10
2840+ 0x04 , 0x00 , // T = 4 (IFLA_HSR_SUPERVISION_ADDR)
2841+ 0x01 , 0x15 , 0x4e , 0x00 , 0x01 , 0x2d , // V = "01:15:4e:00:01:2d"
2842+ 0x00 , 0x00 , // padding
2843+
2844+ 0x06 , 0x00 , // L = 6
2845+ 0x05 , 0x00 , // T = 5 (IFLA_HSR_SEQ_NR)
2846+ 0x4b , 0xfc , // V = 64587
2847+ 0x00 , 0x00 , // padding
2848+
2849+ 0x05 , 0x00 , // L = 5
2850+ 0x07 , 0x00 , // T = 7 (IFLA_HSR_PROTOCOL)
2851+ 0x01 , // V = 1 (HSR_PROTOCOL_PRP)
2852+ 0x00 , 0x00 , 0x00 // padding
2853+ ] ;
2854+
2855+ lazy_static ! {
2856+ static ref HSR_INFO : Vec <InfoHsr > = vec![
2857+ InfoHsr :: Port1 ( 24 ) ,
2858+ InfoHsr :: Port2 ( 26 ) ,
2859+ InfoHsr :: SupervisionAddr ( [ 0x01 , 0x15 , 0x4e , 0x00 , 0x01 , 0x2d ] ) ,
2860+ InfoHsr :: SeqNr ( 64587 ) ,
2861+ InfoHsr :: Protocol ( HsrProtocol :: Prp ) ,
2862+ ] ;
2863+ }
2864+
2865+ #[ test]
2866+ fn parse_info_hsr ( ) {
2867+ let nla = NlaBuffer :: new_checked ( & HSR [ ..] ) . unwrap ( ) ;
2868+ let parsed = VecInfo :: parse ( & nla) . unwrap ( ) . 0 ;
2869+ let expected = vec ! [
2870+ Info :: Kind ( InfoKind :: Hsr ) ,
2871+ Info :: Data ( InfoData :: Hsr ( HSR_INFO . clone( ) ) ) ,
2872+ ] ;
2873+ assert_eq ! ( expected, parsed) ;
2874+ }
2875+
2876+ #[ test]
2877+ fn emit_info_hsr ( ) {
2878+ let nlas = vec ! [
2879+ Info :: Kind ( InfoKind :: Hsr ) ,
2880+ Info :: Data ( InfoData :: Hsr ( HSR_INFO . clone( ) ) ) ,
2881+ ] ;
2882+
2883+ assert_eq ! ( nlas. as_slice( ) . buffer_len( ) , HSR . len( ) ) ;
2884+
2885+ let mut vec = vec ! [ 0xff ; HSR . len( ) ] ;
2886+ nlas. as_slice ( ) . emit ( & mut vec) ;
2887+ assert_eq ! ( & vec[ ..] , & HSR [ ..] ) ;
2888+ }
26772889}
0 commit comments