Skip to content

Commit

Permalink
vxlan: convert some attributes from Vec<u8> to IP address
Browse files Browse the repository at this point in the history
Attributes "Group", "Group6", "Local" and "Local6" are currently
stored as a Vec<u8>, however they represent IP addresses. Change their
type.

Signed-off-by: Beniamino Galvani <bgalvani@redhat.com>
  • Loading branch information
bengal authored and cathay4t committed Sep 4, 2024
1 parent 7391b19 commit 538e13b
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 19 deletions.
85 changes: 68 additions & 17 deletions src/link/link_info/vxlan.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: MIT

use std::net::{Ipv4Addr, Ipv6Addr};

use anyhow::Context;
use byteorder::{BigEndian, ByteOrder, NativeEndian};
use netlink_packet_utils::{
Expand Down Expand Up @@ -45,11 +47,11 @@ const IFLA_VXLAN_LOCALBYPASS: u16 = 31;
#[non_exhaustive]
pub enum InfoVxlan {
Id(u32),
Group(Vec<u8>),
Group6(Vec<u8>),
Group(Ipv4Addr),
Group6(Ipv6Addr),
Link(u32),
Local(Vec<u8>),
Local6(Vec<u8>),
Local(Ipv4Addr),
Local6(Ipv6Addr),
Tos(u8),
Ttl(u8),
Label(u32),
Expand Down Expand Up @@ -105,11 +107,10 @@ impl Nla for InfoVxlan {
| Self::Link(_)
| Self::Ageing(_)
| Self::Limit(_)
| Self::PortRange(_) => 4,
Self::Local(bytes)
| Self::Local6(bytes)
| Self::Group(bytes)
| Self::Group6(bytes) => bytes.len(),
| Self::PortRange(_)
| Self::Group(_)
| Self::Local(_) => 4,
Self::Group6(_) | Self::Local6(_) => 16,
Self::Other(nla) => nla.value_len(),
}
}
Expand Down Expand Up @@ -141,10 +142,12 @@ impl Nla for InfoVxlan {
| Self::RemCsumTX(value)
| Self::RemCsumRX(value)
| Self::TtlInherit(value) => buffer[0] = *value as u8,
Self::Local(value)
| Self::Group(value)
| Self::Group6(value)
| Self::Local6(value) => buffer.copy_from_slice(value.as_slice()),
Self::Group(value) | Self::Local(value) => {
buffer.copy_from_slice(&value.octets())
}
Self::Group6(value) | Self::Local6(value) => {
buffer.copy_from_slice(&value.octets())
}
Self::Port(value) => BigEndian::write_u16(buffer, *value),
Self::PortRange(range) => {
BigEndian::write_u16(buffer, range.0);
Expand Down Expand Up @@ -199,13 +202,61 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVxlan {
IFLA_VXLAN_ID => {
Self::Id(parse_u32(payload).context("invalid IFLA_VXLAN_ID value")?)
}
IFLA_VXLAN_GROUP => Self::Group(payload.to_vec()),
IFLA_VXLAN_GROUP6 => Self::Group6(payload.to_vec()),
IFLA_VXLAN_GROUP => {
if payload.len() == 4 {
let mut data = [0u8; 4];
data.copy_from_slice(&payload[0..4]);
Self::Group(Ipv4Addr::from(data))
} else {
return Err(DecodeError::from(format!(
"Invalid IFLA_VXLAN_GROUP, got unexpected length \
of IPv4 address payload {:?}",
payload
)));
}
}
IFLA_VXLAN_LOCAL => {
if payload.len() == 4 {
let mut data = [0u8; 4];
data.copy_from_slice(&payload[0..4]);
Self::Local(Ipv4Addr::from(data))
} else {
return Err(DecodeError::from(format!(
"Invalid IFLA_VXLAN_LOCAL, got unexpected length \
of IPv4 address payload {:?}",
payload
)));
}
}
IFLA_VXLAN_GROUP6 => {
if payload.len() == 16 {
let mut data = [0u8; 16];
data.copy_from_slice(&payload[0..16]);
Self::Group6(Ipv6Addr::from(data))
} else {
return Err(DecodeError::from(format!(
"Invalid IFLA_VXLAN_GROUP6, got unexpected length \
of IPv6 address payload {:?}",
payload
)));
}
},
IFLA_VXLAN_LOCAL6 => {
if payload.len() == 16 {
let mut data = [0u8; 16];
data.copy_from_slice(&payload[0..16]);
Self::Local6(Ipv6Addr::from(data))
} else {
return Err(DecodeError::from(format!(
"Invalid IFLA_VXLAN_LOCAL6, got unexpected length \
of IPv6 address payload {:?}",
payload
)));
}
},
IFLA_VXLAN_LINK => Self::Link(
parse_u32(payload).context("invalid IFLA_VXLAN_LINK value")?,
),
IFLA_VXLAN_LOCAL => Self::Local(payload.to_vec()),
IFLA_VXLAN_LOCAL6 => Self::Local6(payload.to_vec()),
IFLA_VXLAN_TOS => {
Self::Tos(parse_u8(payload)
.context("invalid IFLA_VXLAN_TOS value")?)
Expand Down
136 changes: 134 additions & 2 deletions src/link/tests/vxlan.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// SPDX-License-Identifier: MIT

use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;

use netlink_packet_utils::{nla::DefaultNla, Emitable, Parseable};

use crate::link::link_flag::LinkFlags;
Expand Down Expand Up @@ -226,9 +229,13 @@ fn test_parsing_link_vxlan() {
LinkInfo::Kind(InfoKind::Vxlan),
LinkInfo::Data(InfoData::Vxlan(vec![
InfoVxlan::Id(101),
InfoVxlan::Group(vec![8, 8, 8, 8]),
InfoVxlan::Group(
Ipv4Addr::from_str("8.8.8.8").unwrap().into(),
),
InfoVxlan::Link(13),
InfoVxlan::Local(vec![1, 1, 1, 1]),
InfoVxlan::Local(
Ipv4Addr::from_str("1.1.1.1").unwrap().into(),
),
InfoVxlan::Ttl(0),
InfoVxlan::TtlInherit(false),
InfoVxlan::Tos(0),
Expand Down Expand Up @@ -376,3 +383,128 @@ fn test_parsing_link_vxlan() {

assert_eq!(buf, raw);
}

#[test]
fn test_parsing_link_vxlan_ipv6() {
let raw = vec![
0x00, 0x00, 0x01, 0x00, 0xbe, 0x69, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x76, 0x78, 0x6c, 0x61,
0x6e, 0x31, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0xe8, 0x03, 0x00, 0x00,
0x05, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x96, 0x05, 0x00, 0x00,
0x08, 0x00, 0x32, 0x00, 0x44, 0x00, 0x00, 0x00, 0x08, 0x00, 0x33, 0x00,
0xff, 0xff, 0x00, 0x00, 0x08, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1f, 0x00,
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0xff, 0xff, 0x00, 0x00,
0x08, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x20, 0x00,
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00,
0x09, 0x00, 0x06, 0x00, 0x6e, 0x6f, 0x6f, 0x70, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x2f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x0a, 0x00, 0x02, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c, 0x00, 0x2b, 0x00,
0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x12, 0x00,
0x0a, 0x00, 0x01, 0x00, 0x76, 0x78, 0x6c, 0x61, 0x6e, 0x00, 0x00, 0x00,
0xec, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x14, 0x00, 0x10, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x03, 0x00,
0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x11, 0x00, 0xfd, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x1c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1a, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0b, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x08, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x08, 0x00, 0x09, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x21, 0x18, 0x00, 0x00,
0x05, 0x00, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x13, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00,
0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
];

let expected = LinkMessage {
header: LinkHeader {
interface_family: AddressFamily::Unspec,
index: 27070,
link_layer_type: LinkLayerType::Ether,
flags: LinkFlags::Broadcast | LinkFlags::Multicast,
change_mask: LinkFlags::empty(),
},
attributes: vec![
LinkAttribute::IfName("vxlan1".into()),
LinkAttribute::TxQueueLen(1000),
LinkAttribute::OperState(State::Down),
LinkAttribute::Mode(0),
LinkAttribute::Mtu(1430),
LinkAttribute::MinMtu(68),
LinkAttribute::MaxMtu(65535),
LinkAttribute::Group(0),
LinkAttribute::Promiscuity(0),
LinkAttribute::NumTxQueues(1),
LinkAttribute::GsoMaxSegs(65535),
LinkAttribute::GsoMaxSize(65536),
LinkAttribute::NumRxQueues(1),
LinkAttribute::Carrier(1),
LinkAttribute::Qdisc("noop".to_string()),
LinkAttribute::CarrierChanges(0),
LinkAttribute::CarrierUpCount(0),
LinkAttribute::CarrierDownCount(0),
LinkAttribute::ProtoDown(0),
LinkAttribute::Address(vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
LinkAttribute::Broadcast(vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff]),
LinkAttribute::Xdp(vec![LinkXdp::Attached(XdpAttached::None)]),
LinkAttribute::LinkInfo(vec![
LinkInfo::Kind(InfoKind::Vxlan),
LinkInfo::Data(InfoData::Vxlan(vec![
InfoVxlan::Id(12),
InfoVxlan::Group6(
Ipv6Addr::from_str("ff00::1").unwrap().into(),
),
InfoVxlan::Link(2),
InfoVxlan::Local6(
Ipv6Addr::from_str("fd01::2").unwrap().into(),
),
InfoVxlan::Ttl(0),
InfoVxlan::TtlInherit(false),
InfoVxlan::Tos(0),
InfoVxlan::Df(0),
InfoVxlan::Label(0),
InfoVxlan::Other(DefaultNla::new(32, vec![0, 0, 0, 0])),
InfoVxlan::Learning(true),
InfoVxlan::Proxy(false),
InfoVxlan::Rsc(false),
InfoVxlan::L2Miss(false),
InfoVxlan::L3Miss(false),
InfoVxlan::CollectMetadata(false),
InfoVxlan::Ageing(300),
InfoVxlan::Limit(0),
InfoVxlan::Port(8472),
InfoVxlan::UDPCsum(true),
InfoVxlan::UDPZeroCsumTX(false),
InfoVxlan::UDPZeroCsumRX(false),
InfoVxlan::RemCsumTX(false),
InfoVxlan::RemCsumRX(false),
InfoVxlan::Localbypass(true),
InfoVxlan::PortRange((0, 0)),
])),
]),
],
};

assert_eq!(
expected,
LinkMessage::parse(&LinkMessageBuffer::new(&raw)).unwrap()
);

let mut buf = vec![0; expected.buffer_len()];

expected.emit(&mut buf);

assert_eq!(buf, raw);
}

0 comments on commit 538e13b

Please sign in to comment.