From 7c56679bc41e04a80e8792c44658a90e95dc3f02 Mon Sep 17 00:00:00 2001 From: Miguel Duarte Barroso Date: Thu, 3 Aug 2023 12:29:27 +0200 Subject: [PATCH] vxlan: fix port-range attribute marshalling Since we were not updating the `buffer` variable when writing to it, the "max" part of the range was over-writing the "min", which caused the netlink message to be considered invalid. By adjusting the buffer to where we write, the netlink add message was properly processed, and the link successfully created. Unit tests were added to assert the expected behavior. Signed-off-by: Miguel Duarte Barroso --- src/rtnl/link/nlas/link_infos.rs | 50 +++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/rtnl/link/nlas/link_infos.rs b/src/rtnl/link/nlas/link_infos.rs index 287bf9f4..83061b68 100644 --- a/src/rtnl/link/nlas/link_infos.rs +++ b/src/rtnl/link/nlas/link_infos.rs @@ -782,7 +782,7 @@ impl Nla for InfoVxlan { Port(ref value) => BigEndian::write_u16(buffer, *value), PortRange(ref range) => { BigEndian::write_u16(buffer, range.0); - BigEndian::write_u16(buffer, range.1) + BigEndian::write_u16(&mut buffer[2..], range.1) } } } @@ -2498,4 +2498,52 @@ mod tests { nlas.as_slice().emit(&mut vec); assert_eq!(&vec[..], &VXLAN[..]); } + + lazy_static! { + static ref VXLAN_INFO_WITH_PORT_RANGE: Vec = + vec![InfoVxlan::Id(10), InfoVxlan::PortRange((9000, 9050)),]; + } + + #[rustfmt::skip] + static VXLAN_WITH_PORT_RANGE: [u8; 32] = [ + 0x0a, 0x00, // length = 10 + 0x01, 0x00, // type = 1 = IFLA_INFO_KIND + 0x76, 0x78, 0x6C, 0x61, 0x6E, // V = "vxlan\0" + 0x00, 0x00, 0x00, // padding + 0x14, 0x00, // length = 20 + 0x02, 0x00, // type = 2 = IFLA_INFO_DATA + 0x08, 0x00, // length - 8 + 0x01, 0x00, // type = 1 = IFLA_VXLAN_ID + 0x0A, 0x00, // id = 0x0A = 10 + 0x00, 0x00, // padding + 0x08, 0x00, // length = 6 + 0x0A, 0x00, // type = 10 = IFLA_VXLAN_PORT_RANGE + 0x23, 0x28, // min port: 9000 + 0x23, 0x5a // max port: 9050 + ]; + + #[test] + fn emit_info_vxlan_with_port_range() { + let nlas = vec![ + Info::Kind(InfoKind::Vxlan), + Info::Data(InfoData::Vxlan(VXLAN_INFO_WITH_PORT_RANGE.clone())), + ]; + + assert_eq!(nlas.as_slice().buffer_len(), VXLAN_WITH_PORT_RANGE.len()); + + let mut vec = vec![0xff; VXLAN_WITH_PORT_RANGE.len()]; + nlas.as_slice().emit(&mut vec); + assert_eq!(&vec[..], &VXLAN_WITH_PORT_RANGE[..]); + } + + #[test] + fn parse_info_vxlan_with_port_range() { + let nla = NlaBuffer::new_checked(&VXLAN_WITH_PORT_RANGE[..]).unwrap(); + let parsed = VecInfo::parse(&nla).unwrap().0; + let expected = vec![ + Info::Kind(InfoKind::Vxlan), + Info::Data(InfoData::Vxlan(VXLAN_INFO_WITH_PORT_RANGE.clone())), + ]; + assert_eq!(expected, parsed); + } }