Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Support setting the bond port settings of the device
Add support for setting device's bond port settings and also provide the example for validating the support. Notice that the port priority setting is supported in kernel since v6.0. Signed-off-by: Wen Liang <liangwen12year@gmail.com>
- Loading branch information
1 parent
9b67c97
commit 7afe563
Showing
5 changed files
with
202 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| use futures::stream::TryStreamExt; | ||
| use rtnetlink::{new_connection, Error, Handle}; | ||
| use std::env; | ||
|
|
||
| #[tokio::main] | ||
| async fn main() -> Result<(), ()> { | ||
| let args: Vec<String> = env::args().collect(); | ||
| if args.len() != 2 { | ||
| usage(); | ||
| return Ok(()); | ||
| } | ||
| let link_name = &args[1]; | ||
|
|
||
| let (connection, handle, _) = new_connection().unwrap(); | ||
| tokio::spawn(connection); | ||
|
|
||
| let linkname = link_name.to_string(); | ||
| println!("dumping bond port settings for link \"{linkname}\""); | ||
|
|
||
| if let Err(e) = dump_bond_port_settings(handle, linkname).await { | ||
| eprintln!("{e}"); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| async fn dump_bond_port_settings( | ||
| handle: Handle, | ||
| linkname: String, | ||
| ) -> Result<(), Error> { | ||
| let mut links = handle.link().get().match_name(linkname.clone()).execute(); | ||
| if let Some(_link) = links.try_next().await? { | ||
| let mut link_messgage = | ||
| handle.link().get().match_name(linkname).execute(); | ||
| while let Some(msg) = link_messgage.try_next().await? { | ||
| println!("{msg:?}"); | ||
| } | ||
| Ok(()) | ||
| } else { | ||
| eprintln!("link {linkname} not found"); | ||
| Ok(()) | ||
| } | ||
| } | ||
|
|
||
| fn usage() { | ||
| eprintln!( | ||
| "usage: | ||
| cargo run --example get_bond_port_settings -- <link name> | ||
| Note that you need to run this program as root. Instead of running cargo as root, | ||
| build the example normally: | ||
| cd netlink-ip ; cargo build --example get_bond_port_settings | ||
| Then find the binary in the target directory: | ||
| cd ../target/debug/example ; sudo ./get_bond_port_settings <link_name>" | ||
| ); | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| use futures::stream::TryStreamExt; | ||
| use rtnetlink::{new_connection, Error, Handle}; | ||
| use std::env; | ||
|
|
||
| #[tokio::main] | ||
| async fn main() -> Result<(), String> { | ||
| let args: Vec<String> = env::args().collect(); | ||
| if args.len() != 2 { | ||
| usage(); | ||
| return Ok(()); | ||
| } | ||
| let link_name = &args[1]; | ||
|
|
||
| let (connection, handle, _) = new_connection().unwrap(); | ||
| tokio::spawn(connection); | ||
|
|
||
| set_bond_port_settings(handle, link_name.to_string()) | ||
| .await | ||
| .map_err(|e| format!("{e}")) | ||
| } | ||
| // The bond port priority is only supported to set when bonding mode is | ||
| // active-backup(1) or balance-tlb (5) or balance-alb (6) | ||
| async fn set_bond_port_settings( | ||
| handle: Handle, | ||
| name: String, | ||
| ) -> Result<(), Error> { | ||
| let mut links = handle.link().get().match_name(name.clone()).execute(); | ||
| if let Some(link) = links.try_next().await? { | ||
| // This is equivalent to `ip link set name NAME type bond_slave queue_id | ||
| // 0 prio 1`. The port priority setting is supported in kernel | ||
| // since v6.0 | ||
| handle | ||
| .link() | ||
| .set_bond_port(link.header.index) | ||
| .queue_id(0) | ||
| .prio(1) | ||
| .execute() | ||
| .await? | ||
| } else { | ||
| println!("no link link {name} found"); | ||
| } | ||
| Ok(()) | ||
| } | ||
|
|
||
| fn usage() { | ||
| eprintln!( | ||
| "usage: | ||
| cargo run --example set_bond_port_settings -- <link name> | ||
| Note that you need to run this program as root. Instead of running cargo as root, | ||
| build the example normally: | ||
| cd netlink-ip ; cargo build --example set_bond_port_settings | ||
| Then find the binary in the target directory: | ||
| cd ../target/debug/example ; sudo ./set_bond_port_settings <link_name>" | ||
| ); | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| use futures::stream::StreamExt; | ||
| use netlink_packet_core::{NetlinkMessage, NLM_F_ACK, NLM_F_REQUEST}; | ||
| use netlink_packet_route::{ | ||
| link::nlas::{Info, InfoBondPort, InfoPortData, InfoPortKind, Nla}, | ||
| LinkMessage, RtnlMessage, | ||
| }; | ||
|
|
||
| use crate::{try_nl, Error, Handle}; | ||
|
|
||
| pub struct BondPortSetRequest { | ||
| handle: Handle, | ||
| index: u32, | ||
| port_nlas: Vec<InfoBondPort>, | ||
| } | ||
|
|
||
| impl BondPortSetRequest { | ||
| pub(crate) fn new(handle: Handle, index: u32) -> Self { | ||
| BondPortSetRequest { | ||
| handle, | ||
| index, | ||
| port_nlas: Vec::new(), | ||
| } | ||
| } | ||
|
|
||
| /// Execute the request. | ||
| pub async fn execute(self) -> Result<(), Error> { | ||
| let BondPortSetRequest { | ||
| mut handle, | ||
| index, | ||
| port_nlas, | ||
| } = self; | ||
|
|
||
| let mut message = LinkMessage::default(); | ||
| message.header.index = index; | ||
| message.nlas.push(Nla::Info(vec![ | ||
| Info::PortKind(InfoPortKind::Bond), | ||
| Info::PortData(InfoPortData::BondPort(port_nlas)), | ||
| ])); | ||
|
|
||
| let mut req = NetlinkMessage::from(RtnlMessage::NewLink(message)); | ||
| req.header.flags = NLM_F_REQUEST | NLM_F_ACK; | ||
|
|
||
| let mut response = handle.request(req)?; | ||
| while let Some(message) = response.next().await { | ||
| try_nl!(message); | ||
| } | ||
| Ok(()) | ||
| } | ||
|
|
||
| /// Return a mutable reference to the Vec<InfoBondPort> | ||
| pub fn info_port_nlas_mut(&mut self) -> &mut Vec<InfoBondPort> { | ||
| &mut self.port_nlas | ||
| } | ||
|
|
||
| /// Adds the `queue_id` attribute to the bond port | ||
| /// This is equivalent to | ||
| /// `ip link set name NAME type bond_slave queue_id QUEUE_ID`. | ||
| pub fn queue_id(mut self, queue_id: u16) -> Self { | ||
| self.port_nlas.push(InfoBondPort::QueueId(queue_id)); | ||
| self | ||
| } | ||
|
|
||
| /// Adds the `prio` attribute to the bond port | ||
| /// This is equivalent to `ip link set name NAME type bond_slave prio PRIO`. | ||
| pub fn prio(mut self, prio: i32) -> Self { | ||
| self.port_nlas.push(InfoBondPort::Prio(prio)); | ||
| self | ||
| } | ||
| } |