From 09700478eb034d9e08175e867157690efb9392f4 Mon Sep 17 00:00:00 2001 From: Ruoqing He Date: Mon, 28 Apr 2025 07:35:04 +0000 Subject: [PATCH 1/2] runtime-rs: Group Dependencies from `rust-netlink` `rtnetlink`, `netlink-sys` and `netlink-packet-route` are from the same organization, and some of them are depending on the others, which implies the version of those crates should be chosen and dealt with carefully, group them to provide better management. Signed-off-by: Ruoqing He --- src/runtime-rs/crates/resource/Cargo.toml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/runtime-rs/crates/resource/Cargo.toml b/src/runtime-rs/crates/resource/Cargo.toml index 3c6cf32bd9..fd2dbccbc3 100644 --- a/src/runtime-rs/crates/resource/Cargo.toml +++ b/src/runtime-rs/crates/resource/Cargo.toml @@ -22,11 +22,8 @@ futures = "0.3.11" lazy_static = { workspace = true } libc = { workspace = true } netns-rs = { workspace = true } -netlink-sys = "0.8.3" -netlink-packet-route = "0.19.0" nix = { workspace = true } rand = { workspace = true } -rtnetlink = "0.14.0" scopeguard = "1.0.0" serde = { workspace = true } serde_json = { workspace = true } @@ -37,6 +34,11 @@ tracing = { workspace = true } uuid = { version = "0.4", features = ["v4"] } oci-spec = { workspace = true } +## Dependencies from `rust-netlink` +netlink-packet-route = "0.19.0" +netlink-sys = "0.8.3" +rtnetlink = "0.14.0" + # Local dependencies agent = { workspace = true } hypervisor = { workspace = true } From 2d0f32ff9660355d365949ea90db8fe09d7f17e6 Mon Sep 17 00:00:00 2001 From: Ruoqing He Date: Mon, 28 Apr 2025 08:37:20 +0000 Subject: [PATCH 2/2] runtime-rs: Upgrade crates from `rust-netlink` Bump `netlink-sys` to v0.8, `netlink-packet-route` to v0.22 and `rtnetlink` to v0.16 to reach a consistent state of `rust-netlink` dependencies. `bitflags` is bumped to v2.9.0 since those crates requires it. Signed-off-by: Ruoqing He --- src/runtime-rs/Cargo.lock | 35 ++++++++++++++---- src/runtime-rs/crates/resource/Cargo.toml | 8 ++-- .../src/network/endpoint/endpoints_test.rs | 37 +++++++++++-------- .../network_info/network_info_from_dan.rs | 4 +- .../network_info/network_info_from_link.rs | 21 ++++++----- .../network_model/test_network_model.rs | 8 ++-- .../resource/src/network/network_pair.rs | 22 ++++++++--- .../resource/src/network/utils/address.rs | 6 +-- .../src/network/utils/link/manager.rs | 21 +++-------- 9 files changed, 92 insertions(+), 70 deletions(-) diff --git a/src/runtime-rs/Cargo.lock b/src/runtime-rs/Cargo.lock index 9230783ad7..c204aa9306 100644 --- a/src/runtime-rs/Cargo.lock +++ b/src/runtime-rs/Cargo.lock @@ -442,6 +442,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "cgroups-rs" version = "0.3.4" @@ -1655,7 +1661,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -2212,11 +2218,12 @@ dependencies = [ [[package]] name = "netlink-packet-route" -version = "0.19.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c171cd77b4ee8c7708da746ce392440cb7bcf618d122ec9ecc607b12938bf4" +checksum = "fc0e7987b28514adf555dc1f9a5c30dfc3e50750bbaffb1aec41ca7b23dcd8e4" dependencies = [ "anyhow", + "bitflags 2.9.0", "byteorder", "libc", "log", @@ -2339,6 +2346,18 @@ dependencies = [ "memoffset 0.9.0", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.9.0", + "cfg-if 1.0.0", + "cfg_aliases", + "libc", +] + [[package]] name = "nom" version = "7.1.3" @@ -2950,7 +2969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "059a34f111a9dee2ce1ac2826a68b24601c4298cfeb1a587c3cb493d5ab46f52" dependencies = [ "libc", - "nix 0.25.1", + "nix 0.27.1", ] [[package]] @@ -3453,7 +3472,7 @@ dependencies = [ "agent", "anyhow", "async-trait", - "bitflags 1.3.2", + "bitflags 2.9.0", "byte-unit 4.0.19", "cgroups-rs", "futures 0.3.28", @@ -3495,9 +3514,9 @@ dependencies = [ [[package]] name = "rtnetlink" -version = "0.14.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b684475344d8df1859ddb2d395dd3dac4f8f3422a1aa0725993cb375fc5caba5" +checksum = "3cb5850b5aa2c9c0ae44f157694bbe85107a2e13d76eb3178d0e3ee96c410f57" dependencies = [ "futures 0.3.28", "log", @@ -3506,7 +3525,7 @@ dependencies = [ "netlink-packet-utils", "netlink-proto", "netlink-sys", - "nix 0.27.1", + "nix 0.29.0", "thiserror 1.0.69", "tokio", ] diff --git a/src/runtime-rs/crates/resource/Cargo.toml b/src/runtime-rs/crates/resource/Cargo.toml index fd2dbccbc3..a96887752b 100644 --- a/src/runtime-rs/crates/resource/Cargo.toml +++ b/src/runtime-rs/crates/resource/Cargo.toml @@ -15,7 +15,7 @@ test-utils = { workspace = true } actix-rt = { workspace = true } anyhow = { workspace = true } async-trait = { workspace = true } -bitflags = "1.2.1" +bitflags = "2.9.0" byte-unit = "4.0.14" cgroups-rs = "0.3.2" futures = "0.3.11" @@ -35,9 +35,9 @@ uuid = { version = "0.4", features = ["v4"] } oci-spec = { workspace = true } ## Dependencies from `rust-netlink` -netlink-packet-route = "0.19.0" -netlink-sys = "0.8.3" -rtnetlink = "0.14.0" +netlink-packet-route = "0.22" +netlink-sys = "0.8" +rtnetlink = "0.16" # Local dependencies agent = { workspace = true } diff --git a/src/runtime-rs/crates/resource/src/network/endpoint/endpoints_test.rs b/src/runtime-rs/crates/resource/src/network/endpoint/endpoints_test.rs index f7200a8a78..bae916893b 100644 --- a/src/runtime-rs/crates/resource/src/network/endpoint/endpoints_test.rs +++ b/src/runtime-rs/crates/resource/src/network/endpoint/endpoints_test.rs @@ -10,6 +10,8 @@ mod tests { use anyhow::{anyhow, Context, Result}; use kata_types::config::hypervisor::TopologyConfigInfo; + use netlink_packet_route::link::MacVlanMode; + use rtnetlink::{LinkDummy, LinkMacVlan, LinkVeth, LinkVlan}; use scopeguard::defer; use tests_utils::load_test_config; use tokio::sync::RwLock; @@ -71,10 +73,11 @@ mod tests { thread_handler.abort(); }); + let dummy = LinkDummy::new(&dummy_name).build(); + if let Ok(()) = handle .link() - .add() - .dummy(dummy_name.clone()) + .add(dummy) .execute() .await .context("failed to create dummy link") @@ -83,12 +86,13 @@ mod tests { .await .expect("failed to get the index of dummy link"); + let vlan = LinkVlan::new(&manual_vlan_iface_name, dummy_index, vlanid).build(); + // since IPVlanEndpoint::new() needs an EXISTING virt_iface (which is created // by containerd normally), we have to manually create a virt_iface. if let Ok(()) = handle .link() - .add() - .vlan(manual_vlan_iface_name.clone(), dummy_index, vlanid) + .add(vlan) .execute() .await .context("failed to create manual veth pair") @@ -187,10 +191,11 @@ mod tests { thread_handler.abort(); }); + let dummy = LinkDummy::new(&dummy_name).build(); + if let Ok(()) = handle .link() - .add() - .dummy(dummy_name.clone()) + .add(dummy) .execute() .await .context("failed to create dummy link") @@ -199,18 +204,17 @@ mod tests { .await .expect("failed to get the index of dummy link"); - // Available MACVLAN MODES - let macvlan_mode_private: u32 = 1; + let macvlan = LinkMacVlan::new( + &manual_macvlan_iface_name, + dummy_index, + MacVlanMode::Private, + ) + .build(); // the mode here does not matter, could be any of available modes if let Ok(()) = handle .link() - .add() - .macvlan( - manual_macvlan_iface_name.clone(), - dummy_index, - macvlan_mode_private, - ) + .add(macvlan) .execute() .await .context("failed to create manual macvlan pair") @@ -318,12 +322,13 @@ mod tests { thread_handler.abort(); }); + let veth = LinkVeth::new("foo", &manual_virt_iface_name).build(); + // since IPVlanEndpoint::new() needs an EXISTING virt_iface (which is created // by containerd normally), we have to manually create a virt_iface. if let Ok(()) = handle .link() - .add() - .veth("foo".to_string(), manual_virt_iface_name.clone()) + .add(veth) .execute() .await .context("failed to create manual veth pair") diff --git a/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_dan.rs b/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_dan.rs index 9d2adfed0d..3f68f46f21 100644 --- a/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_dan.rs +++ b/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_dan.rs @@ -7,7 +7,7 @@ use agent::{ARPNeighbor, IPAddress, Interface, Route}; use anyhow::Result; use async_trait::async_trait; -use netlink_packet_route::link::LinkFlag::Noarp; +use netlink_packet_route::link::LinkFlags; use super::NetworkInfo; use crate::network::dan::DanDevice; @@ -55,7 +55,7 @@ impl NetworkInfoFromDan { hw_addr: dan_device.guest_mac.clone(), device_path: String::default(), field_type: dan_device.network_info.interface.ntype.clone(), - raw_flags: dan_device.network_info.interface.flags & u32::from(Noarp), + raw_flags: dan_device.network_info.interface.flags & LinkFlags::Noarp.bits(), }; let routes = dan_device diff --git a/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_link.rs b/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_link.rs index f1a17cc245..284f042930 100644 --- a/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_link.rs +++ b/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_link.rs @@ -4,7 +4,10 @@ // SPDX-License-Identifier: Apache-2.0 // -use std::{convert::TryFrom, net::IpAddr}; +use std::{ + convert::TryFrom, + net::{IpAddr, Ipv4Addr, Ipv6Addr}, +}; use agent::{ARPNeighbor, IPAddress, IPFamily, Interface, Route}; use anyhow::{anyhow, Context, Result}; @@ -15,6 +18,7 @@ use netlink_packet_route::{ neighbour::{NeighbourAddress, NeighbourAttribute, NeighbourMessage}, route::{RouteAddress, RouteAttribute, RouteMessage}, }; +use rtnetlink::{IpVersion, RouteMessageBuilder}; use super::NetworkInfo; use crate::network::utils::{ @@ -168,11 +172,6 @@ fn generate_route(name: &str, route_msg: &RouteMessage) -> Result> return Ok(None); } - let mut flags: u32 = 0; - for flag in &route_msg.header.flags { - flags |= u32::from(*flag); - } - let mut route = Route { scope: u8::from(route_msg.header.scope) as u32, device: name.to_string(), @@ -181,7 +180,7 @@ fn generate_route(name: &str, route_msg: &RouteMessage) -> Result> } else { IPFamily::V6 }, - flags, + flags: route_msg.header.flags.bits(), ..Default::default() }; @@ -212,10 +211,14 @@ async fn get_route_from_msg( routes: &mut Vec, handle: &rtnetlink::Handle, attrs: &LinkAttrs, - ip_version: rtnetlink::IpVersion, + ip_version: IpVersion, ) -> Result<()> { let name = &attrs.name; - let mut route_msg_list = handle.route().get(ip_version).execute(); + let route_message = match ip_version { + IpVersion::V4 => RouteMessageBuilder::::new().build(), + IpVersion::V6 => RouteMessageBuilder::::new().build(), + }; + let mut route_msg_list = handle.route().get(route_message).execute(); while let Some(route_msg) = route_msg_list.try_next().await? { // get route filter with index for attr in &route_msg.attributes { diff --git a/src/runtime-rs/crates/resource/src/network/network_model/test_network_model.rs b/src/runtime-rs/crates/resource/src/network/network_model/test_network_model.rs index bd1bb628f2..96105f9f17 100644 --- a/src/runtime-rs/crates/resource/src/network/network_model/test_network_model.rs +++ b/src/runtime-rs/crates/resource/src/network/network_model/test_network_model.rs @@ -11,6 +11,7 @@ mod tests { network_pair::NetworkPair, }; use anyhow::Context; + use rtnetlink::LinkVeth; use scopeguard::defer; #[actix_rt::test] async fn test_tc_redirect_network() { @@ -20,10 +21,9 @@ mod tests { thread_handler.abort(); }); - handle - .link() - .add() - .veth("foo".to_string(), "bar".to_string()); + let veth = LinkVeth::new("foo", "bar").build(); + + handle.link().add(veth); if let Ok(net_pair) = NetworkPair::new(&handle, 1, "bar", TC_FILTER_NET_MODEL_STR, 2).await diff --git a/src/runtime-rs/crates/resource/src/network/network_pair.rs b/src/runtime-rs/crates/resource/src/network/network_pair.rs index 1816feb6b7..a5cfa47ea1 100644 --- a/src/runtime-rs/crates/resource/src/network/network_pair.rs +++ b/src/runtime-rs/crates/resource/src/network/network_pair.rs @@ -8,6 +8,7 @@ use std::{convert::TryFrom, sync::Arc}; use anyhow::{anyhow, Context, Result}; use futures::stream::TryStreamExt; +use rtnetlink::LinkUnspec; use super::{ network_model, @@ -88,16 +89,22 @@ impl NetworkPair { handle .link() - .set(tap_link.attrs().index) - .mtu(virt_link.attrs().mtu) + .set( + LinkUnspec::new_with_index(tap_link.attrs().index) + .mtu(virt_link.attrs().mtu) + .build(), + ) .execute() .await .context("set link mtu")?; handle .link() - .set(tap_link.attrs().index) - .up() + .set( + LinkUnspec::new_with_index(tap_link.attrs().index) + .up() + .build(), + ) .execute() .await .context("set link up")?; @@ -156,8 +163,11 @@ pub async fn create_link( if base.master_index != 0 { handle .link() - .set(base.index) - .controller(base.master_index) + .set( + LinkUnspec::new_with_index(base.index) + .controller(base.master_index) + .build(), + ) .execute() .await .context("set index")?; diff --git a/src/runtime-rs/crates/resource/src/network/utils/address.rs b/src/runtime-rs/crates/resource/src/network/utils/address.rs index 9d623743c9..b18a486407 100644 --- a/src/runtime-rs/crates/resource/src/network/utils/address.rs +++ b/src/runtime-rs/crates/resource/src/network/utils/address.rs @@ -58,11 +58,7 @@ impl TryFrom for Address { AddressAttribute::Flags(f) => { //since the AddressAttribute::Flags(f) didn't implemented the u32 from trait, //thus here just implemeted a simple transformer. - let mut d: u32 = 0; - for flag in &f { - d |= u32::from(*flag); - } - addr.flags = d; + addr.flags = f.bits(); } AddressAttribute::CacheInfo(_c) => {} _ => {} diff --git a/src/runtime-rs/crates/resource/src/network/utils/link/manager.rs b/src/runtime-rs/crates/resource/src/network/utils/link/manager.rs index 5bd57635f6..66910a5365 100644 --- a/src/runtime-rs/crates/resource/src/network/utils/link/manager.rs +++ b/src/runtime-rs/crates/resource/src/network/utils/link/manager.rs @@ -5,26 +5,15 @@ // use netlink_packet_route::link::{ - InfoBridge, InfoData, InfoKind, LinkAttribute, LinkFlag, LinkInfo, LinkMessage, + InfoBridge, InfoData, InfoKind, LinkAttribute, LinkInfo, LinkMessage, }; use super::{Link, LinkAttrs}; -pub(crate) struct VecLinkFlag(pub Vec); - -impl From<&VecLinkFlag> for u32 { - fn from(v: &VecLinkFlag) -> u32 { - let mut d: u32 = 0; - for flag in &v.0 { - d |= u32::from(*flag); - } - d - } -} - #[allow(clippy::box_default)] pub fn get_link_from_message(mut msg: LinkMessage) -> Box { - let flags = u32::from(&VecLinkFlag(msg.header.flags)); + let flags = msg.header.flags.bits(); + let mut base = LinkAttrs { index: msg.header.index, flags, @@ -65,7 +54,7 @@ pub fn get_link_from_message(mut msg: LinkMessage) -> Box { LinkAttribute::Stats64(_s) => {} LinkAttribute::Xdp(_x) => {} LinkAttribute::OperState(_) => {} - LinkAttribute::NetnsId(n) => { + LinkAttribute::LinkNetNsId(n) => { base.net_ns_id = n; } LinkAttribute::GsoMaxSize(i) => { @@ -187,7 +176,7 @@ fn parse_bridge(mut ibs: Vec) -> Bridge { bridge.multicast_snooping = m == 1; } InfoBridge::VlanFiltering(v) => { - bridge.vlan_filtering = v == 1; + bridge.vlan_filtering = v; } _ => {} }