Skip to content
Merged
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
78 changes: 67 additions & 11 deletions examples/set_bridge_vlan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,9 @@ async fn set_bridge_vlan(
Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (connection, handle, _) = new_connection().unwrap();
tokio::spawn(connection);

let bridge_index = create_bridge_and_get_index(&handle).await?;

let port_index =
create_dummy_and_attach_to_bridge(&handle, bridge_index).await?;
set_bridge_vlan(&handle, bridge_index, port_index).await?;

async fn dump_bridge_vlan(
handle: &rtnetlink::Handle,
) -> Result<(), rtnetlink::Error> {
let mut dump_link = handle
.link()
.get()
Expand Down Expand Up @@ -138,3 +130,67 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
Ok(())
}

async fn del_bridge_vlan(
handle: &Handle,
bridge_index: u32,
port_index: u32,
) -> Result<(), rtnetlink::Error> {
let message = LinkBridgeVlan::new(port_index)
.vlan(10, BridgeVlanInfoFlags::Pvid)
.vlan_range_start(20, BridgeVlanInfoFlags::empty())
.vlan_range_end(30, BridgeVlanInfoFlags::empty())
.build();

handle.link().del_with_message(message).execute().await?;

let message = LinkBridgeVlan::new(bridge_index)
.bridge_self()
.vlan(40, BridgeVlanInfoFlags::Pvid)
.vlan_range_start(50, BridgeVlanInfoFlags::empty())
.vlan_range_end(60, BridgeVlanInfoFlags::empty())
.build();
Comment on lines +139 to +152

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There's significant code duplication between this function (del_bridge_vlan) and set_bridge_vlan. The logic for building the LinkMessage for both the port and the bridge is identical in both functions.

To improve maintainability and reduce redundancy, consider extracting the message creation logic into separate helper functions. This would make the example cleaner and easier to understand.

For example:

fn build_port_vlan_msg(port_index: u32) -> rtnetlink::packet_route::link::LinkMessage {
    LinkBridgeVlan::new(port_index)
        .vlan(10, BridgeVlanInfoFlags::Pvid)
        .vlan_range_start(20, BridgeVlanInfoFlags::empty())
        .vlan_range_end(30, BridgeVlanInfoFlags::empty())
        .build()
}

fn build_bridge_self_vlan_msg(bridge_index: u32) -> rtnetlink::packet_route::link::LinkMessage {
    LinkBridgeVlan::new(bridge_index)
        .bridge_self()
        .vlan(40, BridgeVlanInfoFlags::Pvid)
        .vlan_range_start(50, BridgeVlanInfoFlags::empty())
        .vlan_range_end(60, BridgeVlanInfoFlags::empty())
        .build()
}

Then you could simplify del_bridge_vlan (and set_bridge_vlan) to use these helpers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is over optimization considering this is example code. I think keeping function simple is more important.


handle.link().del_with_message(message).execute().await?;

Ok(())
}

async fn cleanup(
handle: &Handle,
bridge_index: u32,
port_index: u32,
) -> Result<(), rtnetlink::Error> {
handle.link().del(bridge_index).execute().await?;
handle.link().del(port_index).execute().await?;

Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (connection, handle, _) = new_connection().unwrap();
tokio::spawn(connection);

let bridge_index = create_bridge_and_get_index(&handle).await?;

let port_index =
create_dummy_and_attach_to_bridge(&handle, bridge_index).await?;

println!("Setting Bridge VLAN");
set_bridge_vlan(&handle, bridge_index, port_index).await?;

dump_bridge_vlan(&handle).await?;

println!("Removing Bridge VLAN");

del_bridge_vlan(&handle, bridge_index, port_index).await?;

dump_bridge_vlan(&handle).await?;

println!("Cleaning up");

cleanup(&handle, bridge_index, port_index).await?;

Ok(())
}
4 changes: 4 additions & 0 deletions src/link/del.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ impl LinkDelRequest {
LinkDelRequest { handle, message }
}

pub fn new_with_message(handle: Handle, message: LinkMessage) -> Self {
LinkDelRequest { handle, message }
}

/// Execute the request
pub async fn execute(self) -> Result<(), Error> {
let LinkDelRequest {
Expand Down
11 changes: 9 additions & 2 deletions src/link/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,19 @@ impl LinkHandle {
LinkDelPropRequest::new(self.0.clone(), index)
}

pub fn del(&mut self, index: u32) -> LinkDelRequest {
pub fn del(&self, index: u32) -> LinkDelRequest {
LinkDelRequest::new(self.0.clone(), index)
}

/// Delete specified information from interface.
/// For example: To delete bridge VLANs, it is required to include
/// LinkMessage of VLAN information to delete.
pub fn del_with_message(&self, message: LinkMessage) -> LinkDelRequest {
LinkDelRequest::new_with_message(self.0.clone(), message)
}

/// Retrieve the list of links (equivalent to `ip link show`)
pub fn get(&mut self) -> LinkGetRequest {
pub fn get(&self) -> LinkGetRequest {
LinkGetRequest::new(self.0.clone())
}

Expand Down