Skip to content

Commit

Permalink
macvlan: unit test
Browse files Browse the repository at this point in the history
Add unit test asserting a macvlan interface can be added / retrieved /
deleted and the expected parameters are there.

Some default settings are set by the kernel - i.e. Flags, BcQueueLen,
BcQueueLenUsed, and MacAddrCount.

Signed-off-by: Miguel Duarte Barroso <[email protected]>
  • Loading branch information
maiqueb committed Jan 10, 2024
1 parent 9ea4ee5 commit 790992b
Showing 1 changed file with 79 additions and 5 deletions.
84 changes: 79 additions & 5 deletions src/link/test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT

use futures::stream::TryStreamExt;
use netlink_packet_route::link::nlas::{InfoData, InfoMacVlan};
use netlink_packet_route::link::{
nlas::{Info, InfoKind, Nla},
LinkMessage,
Expand All @@ -17,14 +18,65 @@ fn create_get_delete_wg() {
let handle = rt.block_on(_create_wg());
assert!(handle.is_ok());
let mut handle = handle.unwrap();
let msg = rt.block_on(_get_wg(&mut handle));
let msg = rt.block_on(_get_iface(&mut handle, IFACE_NAME.to_owned()));
assert!(msg.is_ok());
let msg = msg.unwrap();
assert!(has_nla(
&msg,
&Nla::Info(vec![Info::Kind(InfoKind::Wireguard)])
));
rt.block_on(_del_wg(&mut handle, msg.header.index)).unwrap();
rt.block_on(_del_iface(&mut handle, msg.header.index))
.unwrap();
}

#[test]
fn create_get_delete_macvlan() {
const MACVLAN_IFACE_NAME: &str = "mvlan1";
const LOWER_DEVICE_IDX: u32 = 2;
const MACVLAN_MODE: u32 = 4; // bridge
let mac_address = &vec![2u8, 0, 0, 0, 0, 1];

let rt = Runtime::new().unwrap();
let handle = rt.block_on(_create_macvlan(
&MACVLAN_IFACE_NAME.to_owned(),
LOWER_DEVICE_IDX, // assuming there's always a network interface in the system ...
MACVLAN_MODE,
mac_address.to_vec(),
));
assert!(handle.is_ok());

let mut handle = handle.unwrap();
let msg =
rt.block_on(_get_iface(&mut handle, MACVLAN_IFACE_NAME.to_owned()));
assert!(msg.is_ok());
assert!(has_nla(
&msg.as_ref().unwrap(),
&Nla::Info(vec![
Info::Kind(InfoKind::MacVlan),
Info::Data(InfoData::MacVlan(vec![
InfoMacVlan::Mode(MACVLAN_MODE),
InfoMacVlan::Flags(0), // defaulted by the kernel
InfoMacVlan::MacAddrCount(0), // defaulted by the kernel
InfoMacVlan::BcQueueLen(1000), // defaulted by the kernel
InfoMacVlan::BcQueueLenUsed(1000) // defaulted by the kernel
]))
])
));
assert!(has_nla(
&msg.as_ref().unwrap(),
&Nla::IfName(MACVLAN_IFACE_NAME.to_string())
));
assert!(has_nla(
&msg.as_ref().unwrap(),
&Nla::Link(LOWER_DEVICE_IDX)
));
assert!(has_nla(
&msg.as_ref().unwrap(),
&Nla::Address(mac_address.to_vec())
));

rt.block_on(_del_iface(&mut handle, msg.unwrap().header.index))
.unwrap();
}

fn has_nla(msg: &LinkMessage, nla: &Nla) -> bool {
Expand All @@ -44,12 +96,34 @@ async fn _create_wg() -> Result<LinkHandle, Error> {
Ok(link_handle)
}

async fn _get_wg(handle: &mut LinkHandle) -> Result<LinkMessage, Error> {
let mut links = handle.get().match_name(IFACE_NAME.to_owned()).execute();
async fn _get_iface(
handle: &mut LinkHandle,
iface_name: String,
) -> Result<LinkMessage, Error> {
let mut links = handle.get().match_name(iface_name).execute();
let msg = links.try_next().await?;
msg.ok_or(Error::RequestFailed)
}

async fn _del_wg(handle: &mut LinkHandle, index: u32) -> Result<(), Error> {
async fn _del_iface(handle: &mut LinkHandle, index: u32) -> Result<(), Error> {
handle.del(index).execute().await
}

async fn _create_macvlan(
name: &String,
lower_device_index: u32,
mode: u32,
mac: Vec<u8>,
) -> Result<LinkHandle, Error> {
let (conn, handle, _) = new_connection().unwrap();
tokio::spawn(conn);
let link_handle = handle.link();
let mut req =
link_handle
.add()
.macvlan(name.to_string(), lower_device_index, mode);
req.message_mut().nlas.push(Nla::IfName(name.to_owned()));
req.message_mut().nlas.push(Nla::Address(mac));
req.execute().await?;
Ok(link_handle)
}

0 comments on commit 790992b

Please sign in to comment.