diff --git a/examples/create_vxcan.rs b/examples/create_vxcan.rs new file mode 100644 index 0000000..e2a38d4 --- /dev/null +++ b/examples/create_vxcan.rs @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT + +use futures_util::stream::TryStreamExt; +use rtnetlink::{new_connection, Error, Handle, LinkUnspec, LinkVxcan}; + +#[tokio::main] +async fn main() -> Result<(), String> { + let (connection, handle, _) = new_connection().unwrap(); + tokio::spawn(connection); + + let link_name = "vxcan0"; + let peer_name = "vxcan0-peer"; + + handle + .link() + .add(LinkVxcan::new(link_name, peer_name).build()) + .execute() + .await + .map_err(|e| format!("{e}"))?; + + set_link_up(&handle, link_name) + .await + .map_err(|e| format!("{e}"))?; + + set_link_up(&handle, peer_name) + .await + .map_err(|e| format!("{e}"))?; + + Ok(()) +} + +async fn set_link_up(handle: &Handle, name: &str) -> Result<(), Error> { + let mut links = handle.link().get().match_name(name.to_string()).execute(); + if let Some(link) = links.try_next().await? { + handle + .link() + .set(LinkUnspec::new_with_index(link.header.index).up().build()) + .execute() + .await? + } else { + println!("no link {name} found"); + } + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index 009c9a3..6c5caed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,7 +53,8 @@ pub use crate::{ LinkBridgeVlan, LinkDelPropRequest, LinkDelRequest, LinkDummy, LinkGetRequest, LinkHandle, LinkMacSec, LinkMacVlan, LinkMacVtap, LinkMessageBuilder, LinkNetkit, LinkSetRequest, LinkUnspec, LinkVeth, - LinkVlan, LinkVrf, LinkVxlan, LinkWireguard, LinkXfrm, QosMapping, + LinkVlan, LinkVrf, LinkVxcan, LinkVxlan, LinkWireguard, LinkXfrm, + QosMapping, }, multicast::MulticastGroup, neighbour::{ diff --git a/src/link/mod.rs b/src/link/mod.rs index 69df943..bb01029 100644 --- a/src/link/mod.rs +++ b/src/link/mod.rs @@ -22,6 +22,7 @@ mod set; mod veth; mod vlan; mod vrf; +mod vxcan; mod vxlan; mod wireguard; mod xfrm; @@ -47,6 +48,7 @@ pub use self::{ veth::LinkVeth, vlan::{LinkVlan, QosMapping}, vrf::LinkVrf, + vxcan::LinkVxcan, vxlan::LinkVxlan, wireguard::LinkWireguard, xfrm::LinkXfrm, diff --git a/src/link/vxcan.rs b/src/link/vxcan.rs new file mode 100644 index 0000000..346bb4d --- /dev/null +++ b/src/link/vxcan.rs @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT + +use crate::{ + packet_route::link::{InfoData, InfoKind, InfoVxcan}, + LinkMessageBuilder, LinkUnspec, +}; + +/// Represent virtual can interface. +/// Example code on creating a vxcan pair +/// ```no_run +/// use rtnetlink::{new_connection, LinkVxcan}; +/// #[tokio::main] +/// async fn main() -> Result<(), String> { +/// let (connection, handle, _) = new_connection().unwrap(); +/// tokio::spawn(connection); +/// +/// handle +/// .link() +/// .add(LinkVxcan::new("vxcan0", "vxcan1").build()) +/// .execute() +/// .await +/// .map_err(|e| format!("{e}")) +/// } +/// ``` +/// +/// Please check LinkMessageBuilder:: for more detail. +#[derive(Debug)] +pub struct LinkVxcan; + +impl LinkVxcan { + /// Equal to `LinkMessageBuilder::::new(name, peer)` + pub fn new(name: &str, peer: &str) -> LinkMessageBuilder { + LinkMessageBuilder::::new(name, peer) + } +} + +impl LinkMessageBuilder { + /// Create [LinkMessageBuilder] for Vxcan + pub fn new(name: &str, peer: &str) -> Self { + LinkMessageBuilder::::new_with_info_kind(InfoKind::Vxcan) + .name(name.to_string()) + .peer(peer) + } + + pub fn peer(mut self, peer: &str) -> Self { + let peer_msg = LinkMessageBuilder::::new() + .name(peer.to_string()) + .build(); + + self.info_data = Some(InfoData::Vxcan(InfoVxcan::Peer(peer_msg))); + self + } +}