Skip to content

Commit

Permalink
macvlan: allow specifying MAC on iface ADD
Browse files Browse the repository at this point in the history
Signed-off-by: Miguel Duarte Barroso <[email protected]>
  • Loading branch information
maiqueb committed Jan 10, 2024
1 parent 5e5c688 commit 9ea4ee5
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ env_logger = "0.10.0"
ipnetwork = "0.18.0"
tokio = { version = "1.0.1", features = ["macros", "rt", "rt-multi-thread"] }
async-std = { version = "1.9.0", features = ["attributes"]}
macaddr = "1.0"
27 changes: 21 additions & 6 deletions examples/create_macvlan.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,52 @@
// SPDX-License-Identifier: MIT

use futures::stream::TryStreamExt;
use macaddr::MacAddr;
use rtnetlink::{new_connection, Error, Handle};
use std::env;
use std::{env, str::FromStr};

use netlink_packet_route::link::nlas::Nla;

#[tokio::main]
async fn main() -> Result<(), String> {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
if args.len() != 2 && args.len() != 3 {
usage();
return Ok(());
}
let link_name = &args[1];
let mac: Option<Vec<u8>> = if args.len() == 3 {
let mac_address_arg = (&args[2]).to_string();
let mac_address = MacAddr::from_str(mac_address_arg.as_str())
.map_err(|e| format!("{e}"))?;
Some(mac_address.as_bytes().into())
} else {
None
};

let (connection, handle, _) = new_connection().unwrap();
tokio::spawn(connection);

create_macvlan(handle, link_name.to_string())
create_macvlan(handle, link_name.to_string(), mac)
.await
.map_err(|e| format!("{e}"))
}

async fn create_macvlan(
handle: Handle,
link_name: String,
mac_address: Option<Vec<u8>>,
) -> Result<(), Error> {
let mut links = handle.link().get().match_name(link_name.clone()).execute();
if let Some(link) = links.try_next().await? {
let request = handle.link().add().macvlan(
let mut request = handle.link().add().macvlan(
"test_macvlan".into(),
link.header.index,
4u32, // bridge mode
);
if let Some(mac) = mac_address {
request.message_mut().nlas.push(Nla::Address(mac));
}
request.execute().await?
} else {
println!("no link {link_name} found");
Expand All @@ -42,7 +57,7 @@ async fn create_macvlan(
fn usage() {
eprintln!(
"usage:
cargo run --example create_macvlan -- <link name>
cargo run --example create_macvlan -- <link name> [mac address]
Note that you need to run this program as root. Instead of running cargo as root,
build the example normally:
Expand All @@ -51,6 +66,6 @@ build the example normally:
Then find the binary in the target directory:
cd target/debug/examples ; sudo ./create_macvlan <link_name>"
cd target/debug/examples ; sudo ./create_macvlan <link_name> [mac address]"
);
}

0 comments on commit 9ea4ee5

Please sign in to comment.