Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions examples/create_ipvlan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: MIT

use std::env;

use futures::stream::TryStreamExt;
use rtnetlink::{
new_connection,
packet_route::link::{IpVlanFlags, IpVlanMode},
Error, Handle, LinkIpVlan,
};

#[tokio::main]
async fn main() -> Result<(), String> {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
usage();
return Ok(());
}
let link_name = &args[1];
let mode_str = &args[2];
let mode = match mode_str.as_str() {
"l2" => IpVlanMode::L2,
"l3" => IpVlanMode::L3,
"l3s" => IpVlanMode::L3S,
_ => {
usage();
return Ok(());
}
};

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

create_ipvlan(handle, link_name.to_string(), mode, IpVlanFlags::empty())
.await
.map_err(|e| format!("{e}"))
}

async fn create_ipvlan(
handle: Handle,
link_name: String,
mode: IpVlanMode,
flag: IpVlanFlags,
) -> Result<(), Error> {
let mut parent_links =
handle.link().get().match_name(link_name.clone()).execute();
if let Some(parent) = parent_links.try_next().await? {
let builder =
LinkIpVlan::new("ipvlan_test", parent.header.index, mode, flag)
.up();
let message = builder.build();
let request = handle.link().add(message);

request.execute().await?
} else {
println!("no link {link_name} found");
}
Ok(())
}

fn usage() {
eprintln!(
"usage:
cargo run --example create_ipvlan -- <link_name> <ipvlan_mode>
ipvlan_mode can be one of the following:
l2: L2 mode
l3: L3 mode
l3s: L3S mode
Note that you need to run this program as root. Instead of running cargo as root,
build the example normally:
cargo build --example create_ipvlan
Then find the binary in the target directory:
cd target/debug/examples ; sudo ./create_ipvlan <link_name> <ipvlan_mode>"
);
}
80 changes: 80 additions & 0 deletions examples/create_ipvtap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: MIT

use std::env;

use futures::stream::TryStreamExt;
use rtnetlink::{
new_connection,
packet_route::link::{IpVtapFlags, IpVtapMode},
Error, Handle, LinkIpVtap,
};

#[tokio::main]
async fn main() -> Result<(), String> {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
usage();
return Ok(());
}
let link_name = &args[1];
let mode_str = &args[2];
let mode = match mode_str.as_str() {
"l2" => IpVtapMode::L2,
"l3" => IpVtapMode::L3,
"l3s" => IpVtapMode::L3S,
_ => {
usage();
return Ok(());
}
};

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

create_ipvtap(handle, link_name.to_string(), mode, IpVtapFlags::empty())
.await
.map_err(|e| format!("{e}"))
}

async fn create_ipvtap(
handle: Handle,
link_name: String,
mode: IpVtapMode,
flags: IpVtapFlags,
) -> Result<(), Error> {
let mut parent_links =
handle.link().get().match_name(link_name.clone()).execute();
if let Some(parent) = parent_links.try_next().await? {
let builder =
LinkIpVtap::new("ipvtap_test", parent.header.index, mode, flags)
.up();
let message = builder.build();
let request = handle.link().add(message);

request.execute().await?
} else {
println!("no link {link_name} found");
}
Ok(())
}

fn usage() {
eprintln!(
"usage:
cargo run --example create_ipvtap -- <link_name> <ipvtap_mode>

ipvtap_mode can be one of the following:
l2: L2 mode
l3: L3 mode
l3s: L3S mode

Note that you need to run this program as root. Instead of running cargo as root,
build the example normally:

cargo build --example create_ipvtap

Then find the binary in the target directory:

cd target/debug/examples ; sudo ./create_ipvtap <link_name> <ipvtap_mode>"
);
}
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ pub use crate::{
handle::Handle,
link::{
LinkAddRequest, LinkBond, LinkBondPort, LinkBridge, LinkDelPropRequest,
LinkDelRequest, LinkDummy, LinkGetRequest, LinkHandle, LinkMacSec,
LinkMacVlan, LinkMacVtap, LinkMessageBuilder, LinkNetkit,
LinkDelRequest, LinkDummy, LinkGetRequest, LinkHandle, LinkIpVlan,
LinkMacSec, LinkMacVlan, LinkMacVtap, LinkMessageBuilder, LinkNetkit,
LinkSetRequest, LinkUnspec, LinkVeth, LinkVlan, LinkVrf, LinkVxlan,
LinkWireguard, LinkXfrm, QosMapping,
},
Expand Down
77 changes: 77 additions & 0 deletions src/link/ip_vlan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: MIT

use crate::{
link::LinkMessageBuilder,
packet_route::link::{
InfoData, InfoIpVlan, InfoKind, IpVlanFlags, IpVlanMode,
},
};

/// Represent IP VLAN interface.
/// Example code on creating a IP VLAN interface
/// ```no_run
/// use rtnetlink::{new_connection, packet_route::link::{IpVlanFlags, IpVlanMode},
/// LinkIpVlan};
///
/// #[tokio::main]
/// async fn main() -> Result<(), String> {
/// let (connection, handle, _) = new_connection().unwrap();
/// tokio::spawn(connection);
///
/// handle
/// .link()
/// .add(
/// LinkIpVlan::new("ipvlan100", 10, IpVlanMode::L2, IpVlanFlags::empty())
/// .up()
/// .build(),
/// )
/// .execute()
/// .await
/// .map_err(|e| format!("{e}"))
/// }
/// ```
///
/// Please check LinkMessageBuilder::<LinkIpVlan> for more detail.
#[derive(Debug)]
pub struct LinkIpVlan;

impl LinkIpVlan {
/// Wrapper of `LinkMessageBuilder::<LinkIpVlan>::new().link().mode()`
pub fn new(
name: &str,
base_iface_index: u32,
mode: IpVlanMode,
flags: IpVlanFlags,
) -> LinkMessageBuilder<Self> {
LinkMessageBuilder::<LinkIpVlan>::new(name)
.link(base_iface_index)
.mode(mode)
.flags(flags)
}
}

impl LinkMessageBuilder<LinkIpVlan> {
/// Create [LinkMessageBuilder] for IP VLAN
pub fn new(name: &str) -> Self {
LinkMessageBuilder::<LinkIpVlan>::new_with_info_kind(InfoKind::IpVlan)
.name(name.to_string())
}

pub fn append_info_data(mut self, info: InfoIpVlan) -> Self {
if let InfoData::IpVlan(infos) = self
.info_data
.get_or_insert_with(|| InfoData::IpVlan(Vec::new()))
{
infos.push(info);
}
self
}

pub fn mode(self, mode: IpVlanMode) -> Self {
self.append_info_data(InfoIpVlan::Mode(mode))
}

pub fn flags(self, flags: IpVlanFlags) -> Self {
self.append_info_data(InfoIpVlan::Flags(flags))
}
}
77 changes: 77 additions & 0 deletions src/link/ip_vtap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: MIT

use crate::{
link::LinkMessageBuilder,
packet_route::link::{
InfoData, InfoIpVtap, InfoKind, IpVtapFlags, IpVtapMode,
},
};

/// Represent IP VTAP interface.
/// Example code on creating a IP VTAP interface
/// ```no_run
/// use rtnetlink::{new_connection, packet_route::link::{IpVtapFlags, IpVtapMode},
/// LinkIpVtap};
///
/// #[tokio::main]
/// async fn main() -> Result<(), String> {
/// let (connection, handle, _) = new_connection().unwrap();
/// tokio::spawn(connection);
///
/// handle
/// .link()
/// .add(
/// LinkIpVtap::new("ipvtap100", 10, IpVtapMode::L2, IpVtapFlags::empty())
/// .up()
/// .build(),
/// )
/// .execute()
/// .await
/// .map_err(|e| format!("{e}"))
/// }
/// ```
///
/// Please check LinkMessageBuilder::<LinkIpVtap> for more detail.
#[derive(Debug)]
pub struct LinkIpVtap;

impl LinkIpVtap {
/// Wrapper of `LinkMessageBuilder::<LinkIpVtap>::new().link().mode()`
pub fn new(
name: &str,
base_iface_index: u32,
mode: IpVtapMode,
flags: IpVtapFlags,
) -> LinkMessageBuilder<Self> {
LinkMessageBuilder::<LinkIpVtap>::new(name)
.link(base_iface_index)
.mode(mode)
.flags(flags)
}
}

impl LinkMessageBuilder<LinkIpVtap> {
/// Create [LinkMessageBuilder] for IP VLAN
pub fn new(name: &str) -> Self {
LinkMessageBuilder::<LinkIpVtap>::new_with_info_kind(InfoKind::IpVtap)
.name(name.to_string())
}

pub fn append_info_data(mut self, info: InfoIpVtap) -> Self {
if let InfoData::IpVtap(infos) = self
.info_data
.get_or_insert_with(|| InfoData::IpVtap(Vec::new()))
{
infos.push(info);
}
self
}

pub fn mode(self, mode: IpVtapMode) -> Self {
self.append_info_data(InfoIpVtap::Mode(mode))
}

pub fn flags(self, flags: IpVtapFlags) -> Self {
self.append_info_data(InfoIpVtap::Flags(flags))
}
}
4 changes: 4 additions & 0 deletions src/link/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ mod del;
mod dummy;
mod get;
mod handle;
mod ip_vlan;
mod ip_vtap;
mod mac_vlan;
mod mac_vtap;
mod macsec;
Expand All @@ -33,6 +35,8 @@ pub use self::{
dummy::LinkDummy,
get::LinkGetRequest,
handle::LinkHandle,
ip_vlan::LinkIpVlan,
ip_vtap::LinkIpVtap,
mac_vlan::LinkMacVlan,
mac_vtap::LinkMacVtap,
macsec::LinkMacSec,
Expand Down