diff --git a/src/rtnl/constants.rs b/src/rtnl/constants.rs index 0a723394..85239719 100644 --- a/src/rtnl/constants.rs +++ b/src/rtnl/constants.rs @@ -470,6 +470,9 @@ pub const IFLA_MACVLAN_MACADDR_MODE: u16 = 3; pub const IFLA_MACVLAN_MACADDR: u16 = 4; pub const IFLA_MACVLAN_MACADDR_DATA: u16 = 5; pub const IFLA_MACVLAN_MACADDR_COUNT: u16 = 6; +pub const IFLA_MACVLAN_BC_QUEUE_LEN: u16 = 7; +pub const IFLA_MACVLAN_BC_QUEUE_LEN_USED: u16 = 8; +pub const IFLA_MACVLAN_BC_CUTOFF: u16 = 9; pub const IFLA_VLAN_UNSPEC: u16 = 0; pub const IFLA_VLAN_ID: u16 = 1; pub const IFLA_VLAN_FLAGS: u16 = 2; diff --git a/src/rtnl/link/nlas/link_infos.rs b/src/rtnl/link/nlas/link_infos.rs index 190476d3..a956c265 100644 --- a/src/rtnl/link/nlas/link_infos.rs +++ b/src/rtnl/link/nlas/link_infos.rs @@ -5,7 +5,8 @@ use byteorder::{ByteOrder, NativeEndian}; use netlink_packet_utils::{ nla::{DefaultNla, Nla, NlaBuffer, NlasIterator}, parsers::{ - parse_mac, parse_string, parse_u16, parse_u16_be, parse_u32, parse_u8, + parse_i32, parse_mac, parse_string, parse_u16, parse_u16_be, parse_u32, + parse_u8, }, traits::{Emitable, Parseable}, DecodeError, @@ -1345,6 +1346,9 @@ pub enum InfoMacVlan { MacAddr([u8; 6]), MacAddrData(Vec), MacAddrCount(u32), + BcQueueLen(u32), + BcQueueLenUsed(u32), + BcCutoff(i32), Other(DefaultNla), } @@ -1359,6 +1363,9 @@ impl Nla for InfoMacVlan { MacAddr(_) => 6, MacAddrData(ref nlas) => nlas.as_slice().buffer_len(), MacAddrCount(_) => 4, + BcQueueLen(_) => 4, + BcQueueLenUsed(_) => 4, + BcCutoff(_) => 4, Other(nla) => nla.value_len(), } } @@ -1373,6 +1380,9 @@ impl Nla for InfoMacVlan { MacAddr(bytes) => buffer.copy_from_slice(bytes), MacAddrData(ref nlas) => nlas.as_slice().emit(buffer), MacAddrCount(value) => NativeEndian::write_u32(buffer, *value), + BcQueueLen(value) => NativeEndian::write_u32(buffer, *value), + BcQueueLenUsed(value) => NativeEndian::write_u32(buffer, *value), + BcCutoff(value) => NativeEndian::write_i32(buffer, *value), Other(nla) => nla.emit_value(buffer), } } @@ -1387,6 +1397,9 @@ impl Nla for InfoMacVlan { MacAddr(_) => IFLA_MACVLAN_MACADDR, MacAddrData(_) => IFLA_MACVLAN_MACADDR_DATA, MacAddrCount(_) => IFLA_MACVLAN_MACADDR_COUNT, + BcQueueLen(_) => IFLA_MACVLAN_BC_QUEUE_LEN, + BcQueueLenUsed(_) => IFLA_MACVLAN_BC_QUEUE_LEN_USED, + BcCutoff(_) => IFLA_MACVLAN_BC_CUTOFF, Other(nla) => nla.kind(), } } @@ -1428,6 +1441,18 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable> for InfoMacVlan { parse_u32(payload) .context("invalid IFLA_MACVLAN_MACADDR_COUNT value")?, ), + IFLA_MACVLAN_BC_QUEUE_LEN => BcQueueLen( + parse_u32(payload) + .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN value")?, + ), + IFLA_MACVLAN_BC_QUEUE_LEN_USED => BcQueueLenUsed( + parse_u32(payload) + .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN_USED value")?, + ), + IFLA_MACVLAN_BC_CUTOFF => BcCutoff( + parse_i32(payload) + .context("invalid IFLA_MACVLAN_BC_CUTOFF value")?, + ), kind => Other( DefaultNla::parse(buf) .context(format!("unknown NLA type {kind}"))?, @@ -1446,6 +1471,9 @@ pub enum InfoMacVtap { MacAddr([u8; 6]), MacAddrData(Vec), MacAddrCount(u32), + BcQueueLen(u32), + BcQueueLenUsed(u32), + BcCutoff(i32), Other(DefaultNla), } @@ -1460,6 +1488,9 @@ impl Nla for InfoMacVtap { MacAddr(_) => 6, MacAddrData(ref nlas) => nlas.as_slice().buffer_len(), MacAddrCount(_) => 4, + BcQueueLen(_) => 4, + BcQueueLenUsed(_) => 4, + BcCutoff(_) => 4, Other(nla) => nla.value_len(), } } @@ -1474,6 +1505,9 @@ impl Nla for InfoMacVtap { MacAddr(bytes) => buffer.copy_from_slice(bytes), MacAddrData(ref nlas) => nlas.as_slice().emit(buffer), MacAddrCount(value) => NativeEndian::write_u32(buffer, *value), + BcQueueLen(value) => NativeEndian::write_u32(buffer, *value), + BcQueueLenUsed(value) => NativeEndian::write_u32(buffer, *value), + BcCutoff(value) => NativeEndian::write_i32(buffer, *value), Other(nla) => nla.emit_value(buffer), } } @@ -1488,6 +1522,9 @@ impl Nla for InfoMacVtap { MacAddr(_) => IFLA_MACVLAN_MACADDR, MacAddrData(_) => IFLA_MACVLAN_MACADDR_DATA, MacAddrCount(_) => IFLA_MACVLAN_MACADDR_COUNT, + BcQueueLen(_) => IFLA_MACVLAN_BC_QUEUE_LEN, + BcQueueLenUsed(_) => IFLA_MACVLAN_BC_QUEUE_LEN_USED, + BcCutoff(_) => IFLA_MACVLAN_BC_CUTOFF, Other(nla) => nla.kind(), } } @@ -1529,6 +1566,18 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable> for InfoMacVtap { parse_u32(payload) .context("invalid IFLA_MACVLAN_MACADDR_COUNT value")?, ), + IFLA_MACVLAN_BC_QUEUE_LEN => BcQueueLen( + parse_u32(payload) + .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN value")?, + ), + IFLA_MACVLAN_BC_QUEUE_LEN_USED => BcQueueLenUsed( + parse_u32(payload) + .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN_USED value")?, + ), + IFLA_MACVLAN_BC_CUTOFF => BcCutoff( + parse_i32(payload) + .context("invalid IFLA_MACVLAN_BC_CUTOFF value")?, + ), kind => Other( DefaultNla::parse(buf) .context(format!("unknown NLA type {kind}"))?, @@ -2142,6 +2191,64 @@ mod tests { assert_eq!(&vec[..], &MACVLAN[..]); } + #[rustfmt::skip] + static MACVLAN_BC: [u8; 48] = [ + 0x0c, 0x00, // length = 12 + 0x01, 0x00, // type = 1 = IFLA_INFO_KIND + 0x6d, 0x61, 0x63, 0x76, 0x6c, 0x61, 0x6e, 0x00, // V = "macvlan\0" + 0x24, 0x00, // length = 36 + 0x02, 0x00, // type = 2 = IFLA_INFO_DATA + 0x08, 0x00, // length = 8 + 0x01, 0x00, // type = IFLA_MACVLAN_MODE + 0x02, 0x00, 0x00, 0x00, // V = 2 = vepa + + 0x08, 0x00, // length = 8 + 0x07, 0x00, // type = IFLA_MACVLAN_BC_QUEUE_LEN + 0xe8, 0x03, 0x00, 0x00, // value 1000 + + 0x08, 0x00, // length = 8 + 0x08, 0x00, // type = IFLA_MACVLAN_BC_QUEUE_LEN_USED + 0xe8, 0x03, 0x00, 0x00, // value 1000 + + 0x08, 0x00, // length = 8 + 0x09, 0x00, // type = IFLA_MACVLAN_BC_CUTOFF + 0xff, 0xff, 0xff, 0xff, // value = -1 (signed two's complement) + ]; + + lazy_static! { + static ref MACVLAN_INFO_BC: Vec = vec![ + InfoMacVlan::Mode(2), // vepa + InfoMacVlan::BcQueueLen(1000), + InfoMacVlan::BcQueueLenUsed(1000), + InfoMacVlan::BcCutoff(-1), + ]; + } + + #[test] + fn parse_info_macvlan_bc() { + let nla = NlaBuffer::new_checked(&MACVLAN_BC[..]).unwrap(); + let parsed = VecInfo::parse(&nla).unwrap().0; + let expected = vec![ + Info::Kind(InfoKind::MacVlan), + Info::Data(InfoData::MacVlan(MACVLAN_INFO_BC.clone())), + ]; + assert_eq!(expected, parsed); + } + + #[test] + fn emit_info_macvlan_bc() { + let nlas = vec![ + Info::Kind(InfoKind::MacVlan), + Info::Data(InfoData::MacVlan(MACVLAN_INFO_BC.clone())), + ]; + + assert_eq!(nlas.as_slice().buffer_len(), 48); + + let mut vec = vec![0xff; 48]; + nlas.as_slice().emit(&mut vec); + assert_eq!(&vec[..], &MACVLAN_BC[..]); + } + lazy_static! { static ref XFRMTUN_INFO: Vec = vec![ InfoXfrmTun::IfId(4), // ifid