1
0
mirror of https://github.com/kata-containers/kata-containers.git synced 2025-05-07 16:07:37 +00:00

Merge pull request from lifupan/route_flags_suport

This commit is contained in:
Xuewei Niu 2025-03-07 18:18:01 +08:00 committed by GitHub
commit 0671252466
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 506 additions and 414 deletions
src
agent
libs/protocols/protos
runtime-rs
runtime/virtcontainers
network.go
pkg/agent/protocols

View File

@ -40,8 +40,9 @@ tokio = { version = "1.39.0", features = ["full"] }
tokio-vsock = "0.3.4"
netlink-sys = { version = "0.7.0", features = ["tokio_socket"] }
rtnetlink = "0.8.0"
netlink-packet-utils = "0.4.1"
rtnetlink = "0.14.0"
netlink-packet-route = "0.19.0"
netlink-packet-core = "0.7.0"
ipnetwork = "0.17.0"
# Note: this crate sets the slog 'max_*' features which allows the log level

View File

@ -6,9 +6,18 @@
use anyhow::{anyhow, Context, Result};
use futures::{future, StreamExt, TryStreamExt};
use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network};
use netlink_packet_route::address::{AddressAttribute, AddressMessage};
use netlink_packet_route::link::{LinkAttribute, LinkMessage};
use netlink_packet_route::neighbour::{self, NeighbourFlag};
use netlink_packet_route::route::{RouteFlag, RouteHeader, RouteProtocol, RouteScope, RouteType};
use netlink_packet_route::{
neighbour::{NeighbourAddress, NeighbourAttribute, NeighbourState},
route::{RouteAddress, RouteAttribute, RouteMessage},
AddressFamily,
};
use nix::errno::Errno;
use protocols::types::{ARPNeighbor, IPAddress, IPFamily, Interface, Route};
use rtnetlink::{new_connection, packet, IpVersion};
use rtnetlink::{new_connection, IpVersion};
use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
@ -35,6 +44,36 @@ impl fmt::Display for LinkFilter<'_> {
}
}
const ALL_RULE_FLAGS: [NeighbourFlag; 8] = [
NeighbourFlag::Use,
NeighbourFlag::Own,
NeighbourFlag::Controller,
NeighbourFlag::Proxy,
NeighbourFlag::ExtLearned,
NeighbourFlag::Offloaded,
NeighbourFlag::Sticky,
NeighbourFlag::Router,
];
const ALL_ROUTE_FLAGS: [RouteFlag; 16] = [
RouteFlag::Dead,
RouteFlag::Pervasive,
RouteFlag::Onlink,
RouteFlag::Offload,
RouteFlag::Linkdown,
RouteFlag::Unresolved,
RouteFlag::Trap,
RouteFlag::Notify,
RouteFlag::Cloned,
RouteFlag::Equalize,
RouteFlag::Prefix,
RouteFlag::LookupTable,
RouteFlag::FibMatch,
RouteFlag::RtOffload,
RouteFlag::RtTrap,
RouteFlag::OffloadFailed,
];
/// A filter to query addresses.
pub enum AddressFilter {
/// Return addresses that belong to the given interface.
@ -74,12 +113,6 @@ impl Handle {
self.enable_link(link.index(), false).await?;
}
// Delete all addresses associated with the link
let addresses = self
.list_addresses(AddressFilter::LinkIndex(link.index()))
.await?;
self.delete_addresses(addresses).await?;
// Add new ip addresses from request
for ip_address in &iface.IPAddresses {
let ip = IpAddr::from_str(ip_address.address())?;
@ -125,6 +158,7 @@ impl Handle {
}
// Update link
let link = self.find_link(LinkFilter::Address(&iface.hwAddr)).await?;
let mut request = self.handle.link().set(link.index());
request.message_mut().header = link.header.clone();
@ -172,26 +206,6 @@ impl Handle {
Ok(())
}
pub async fn update_routes<I>(&mut self, list: I) -> Result<()>
where
I: IntoIterator<Item = Route>,
{
let old_routes = self
.query_routes(None)
.await
.with_context(|| "Failed to query old routes")?;
self.delete_routes(old_routes)
.await
.with_context(|| "Failed to delete old routes")?;
self.add_routes(list)
.await
.with_context(|| "Failed to add new routes")?;
Ok(())
}
/// Retireve available network interfaces.
pub async fn list_interfaces(&self) -> Result<Vec<Interface>> {
let mut list = Vec::new();
@ -225,7 +239,7 @@ impl Handle {
let request = self.handle.link().get();
let filtered = match filter {
LinkFilter::Name(name) => request.set_name_filter(name.to_owned()),
LinkFilter::Name(name) => request.match_name(name.to_owned()),
LinkFilter::Index(index) => request.match_index(index),
_ => request, // Post filters
};
@ -233,7 +247,7 @@ impl Handle {
let mut stream = filtered.execute();
let next = if let LinkFilter::Address(addr) = filter {
use packet::link::nlas::Nla;
use LinkAttribute as Nla;
let mac_addr = parse_mac_address(addr)
.with_context(|| format!("Failed to parse MAC address: {}", addr))?;
@ -242,7 +256,7 @@ impl Handle {
// we may have to dump link list and then find the target link.
stream
.try_filter(|f| {
let result = f.nlas.iter().any(|n| match n {
let result = f.attributes.iter().any(|n| match n {
Nla::Address(data) => data.eq(&mac_addr),
_ => false,
});
@ -278,10 +292,7 @@ impl Handle {
Ok(())
}
async fn query_routes(
&self,
ip_version: Option<IpVersion>,
) -> Result<Vec<packet::RouteMessage>> {
async fn query_routes(&self, ip_version: Option<IpVersion>) -> Result<Vec<RouteMessage>> {
let list = if let Some(ip_version) = ip_version {
self.handle
.route()
@ -321,36 +332,46 @@ impl Handle {
for msg in self.query_routes(None).await? {
// Ignore non-main tables
if msg.header.table != packet::constants::RT_TABLE_MAIN {
if msg.header.table != RouteHeader::RT_TABLE_MAIN {
continue;
}
let mut route = Route {
scope: msg.header.scope as _,
scope: u8::from(msg.header.scope) as u32,
..Default::default()
};
if let Some((ip, mask)) = msg.destination_prefix() {
route.dest = format!("{}/{}", ip, mask);
}
if let Some((ip, mask)) = msg.source_prefix() {
route.source = format!("{}/{}", ip, mask);
}
if let Some(addr) = msg.gateway() {
route.gateway = addr.to_string();
// For gateway, destination is 0.0.0.0
route.dest = if addr.is_ipv4() {
String::from("0.0.0.0")
} else {
String::from("::1")
for attribute in &msg.attributes {
if let RouteAttribute::Destination(dest) = attribute {
if let Ok(dest) = parse_route_addr(dest) {
route.dest = format!("{}/{}", dest, msg.header.destination_prefix_length);
}
}
}
if let Some(index) = msg.output_interface() {
route.device = self.find_link(LinkFilter::Index(index)).await?.name();
if let RouteAttribute::Source(src) = attribute {
if let Ok(src) = parse_route_addr(src) {
route.source = format!("{}/{}", src, msg.header.source_prefix_length)
}
}
if let RouteAttribute::Gateway(g) = attribute {
if let Ok(addr) = parse_route_addr(g) {
// For gateway, destination is 0.0.0.0
if addr.is_ipv4() {
route.dest = String::from("0.0.0.0");
} else {
route.dest = String::from("::1");
}
}
route.gateway = parse_route_addr(g)
.map(|g| g.to_string())
.unwrap_or_default();
}
if let RouteAttribute::Oif(index) = attribute {
route.device = self.find_link(LinkFilter::Index(*index)).await?.name();
}
}
if !route.dest.is_empty() {
@ -361,10 +382,11 @@ impl Handle {
Ok(result)
}
/// Adds a list of routes from iterable object `I`.
/// Add a list of routes from iterable object `I`.
/// If the route existed, then replace it with the latest.
/// It can accept both a collection of routes or a single item (via `iter::once()`).
/// It'll also take care of proper order when adding routes (gateways first, everything else after).
async fn add_routes<I>(&mut self, list: I) -> Result<()>
pub async fn update_routes<I>(&mut self, list: I) -> Result<()>
where
I: IntoIterator<Item = Route>,
{
@ -377,24 +399,41 @@ impl Handle {
for route in list {
let link = self.find_link(LinkFilter::Name(&route.device)).await?;
const MAIN_TABLE: u8 = packet::constants::RT_TABLE_MAIN;
const UNICAST: u8 = packet::constants::RTN_UNICAST;
const BOOT_PROT: u8 = packet::constants::RTPROT_BOOT;
const MAIN_TABLE: u32 = libc::RT_TABLE_MAIN as u32;
let uni_cast: RouteType = RouteType::from(libc::RTN_UNICAST);
let boot_prot: RouteProtocol = RouteProtocol::from(libc::RTPROT_BOOT);
let scope = route.scope as u8;
let scope = RouteScope::from(route.scope as u8);
use packet::nlas::route::Nla;
use RouteAttribute as Nla;
// Build a common indeterminate ip request
let request = self
let mut request = self
.handle
.route()
.add()
.table(MAIN_TABLE)
.kind(UNICAST)
.protocol(BOOT_PROT)
.table_id(MAIN_TABLE)
.kind(uni_cast)
.protocol(boot_prot)
.scope(scope);
let message = request.message_mut();
// calculate the Flag vec from the u32 flags
let mut got: u32 = 0;
let mut flags = Vec::new();
for flag in ALL_ROUTE_FLAGS {
if (route.flags & (u32::from(flag))) > 0 {
flags.push(flag);
got += u32::from(flag);
}
}
if got != route.flags {
flags.push(RouteFlag::Other(route.flags - got));
}
message.header.flags = flags;
// `rtnetlink` offers a separate request builders for different IP versions (IP v4 and v6).
// This if branch is a bit clumsy because it does almost the same.
if route.family() == IPFamily::v6 {
@ -408,7 +447,8 @@ impl Handle {
let mut request = request
.v6()
.destination_prefix(dest_addr.ip(), dest_addr.prefix())
.output_interface(link.index());
.output_interface(link.index())
.replace();
if !route.source.is_empty() {
let network = Ipv6Network::from_str(&route.source)?;
@ -417,8 +457,8 @@ impl Handle {
} else {
request
.message_mut()
.nlas
.push(Nla::PrefSource(network.ip().octets().to_vec()));
.attributes
.push(Nla::PrefSource(RouteAddress::from(network.ip())));
}
}
@ -428,14 +468,16 @@ impl Handle {
}
if let Err(rtnetlink::Error::NetlinkError(message)) = request.execute().await {
if Errno::from_i32(message.code.abs()) != Errno::EEXIST {
return Err(anyhow!(
"Failed to add IP v6 route (src: {}, dst: {}, gtw: {},Err: {})",
route.source(),
route.dest(),
route.gateway(),
message
));
if let Some(code) = message.code {
if Errno::from_i32(code.get()) != Errno::EEXIST {
return Err(anyhow!(
"Failed to add IP v6 route (src: {}, dst: {}, gtw: {},Err: {})",
route.source(),
route.dest(),
route.gateway(),
message
));
}
}
}
} else {
@ -449,7 +491,8 @@ impl Handle {
let mut request = request
.v4()
.destination_prefix(dest_addr.ip(), dest_addr.prefix())
.output_interface(link.index());
.output_interface(link.index())
.replace();
if !route.source.is_empty() {
let network = Ipv4Network::from_str(&route.source)?;
@ -458,8 +501,8 @@ impl Handle {
} else {
request
.message_mut()
.nlas
.push(Nla::PrefSource(network.ip().octets().to_vec()));
.attributes
.push(RouteAttribute::PrefSource(RouteAddress::from(network.ip())));
}
}
@ -469,14 +512,16 @@ impl Handle {
}
if let Err(rtnetlink::Error::NetlinkError(message)) = request.execute().await {
if Errno::from_i32(message.code.abs()) != Errno::EEXIST {
return Err(anyhow!(
"Failed to add IP v4 route (src: {}, dst: {}, gtw: {},Err: {})",
route.source(),
route.dest(),
route.gateway(),
message
));
if let Some(code) = message.code {
if Errno::from_i32(code.get()) != Errno::EEXIST {
return Err(anyhow!(
"Failed to add IP v4 route (src: {}, dst: {}, gtw: {},Err: {})",
route.source(),
route.dest(),
route.gateway(),
message
));
}
}
}
}
@ -485,34 +530,6 @@ impl Handle {
Ok(())
}
async fn delete_routes<I>(&mut self, routes: I) -> Result<()>
where
I: IntoIterator<Item = packet::RouteMessage>,
{
for route in routes.into_iter() {
if route.header.protocol == packet::constants::RTPROT_KERNEL {
continue;
}
let index = if let Some(index) = route.output_interface() {
index
} else {
continue;
};
let link = self.find_link(LinkFilter::Index(index)).await?;
let name = link.name();
if name.contains("lo") || name.contains("::1") {
continue;
}
self.handle.route().del(route).execute().await?;
}
Ok(())
}
async fn list_addresses<F>(&self, filter: F) -> Result<Vec<Address>>
where
F: Into<Option<AddressFilter>>,
@ -534,6 +551,8 @@ impl Handle {
Ok(list)
}
// add the addresses to the specified interface, if the addresses existed,
// replace it with the latest one.
async fn add_addresses<I>(&mut self, index: u32, list: I) -> Result<()>
where
I: IntoIterator<Item = IpNetwork>,
@ -542,6 +561,7 @@ impl Handle {
self.handle
.address()
.add(index, net.ip(), net.prefix())
.replace()
.execute()
.await
.map_err(|err| anyhow!("Failed to add address {}: {:?}", net.ip(), err))?;
@ -550,17 +570,6 @@ impl Handle {
Ok(())
}
async fn delete_addresses<I>(&mut self, list: I) -> Result<()>
where
I: IntoIterator<Item = Address>,
{
for addr in list.into_iter() {
self.handle.address().del(addr.0).execute().await?;
}
Ok(())
}
pub async fn add_arp_neighbors<I>(&mut self, list: I) -> Result<()>
where
I: IntoIterator<Item = ARPNeighbor>,
@ -592,52 +601,57 @@ impl Handle {
.map_err(|e| anyhow!("Failed to parse IP {}: {:?}", ip_address, e))?;
// Import rtnetlink objects that make sense only for this function
use packet::constants::{
NDA_UNSPEC, NLM_F_ACK, NLM_F_CREATE, NLM_F_REPLACE, NLM_F_REQUEST,
};
use packet::neighbour::{NeighbourHeader, NeighbourMessage};
use packet::nlas::neighbour::Nla;
use packet::{NetlinkMessage, NetlinkPayload, RtnlMessage};
use libc::{NDA_UNSPEC, NLM_F_ACK, NLM_F_CREATE, NLM_F_REPLACE, NLM_F_REQUEST};
use neighbour::{NeighbourHeader, NeighbourMessage};
use netlink_packet_core::{NetlinkMessage, NetlinkPayload};
use netlink_packet_route::RouteNetlinkMessage as RtnlMessage;
use rtnetlink::Error;
const IFA_F_PERMANENT: u16 = 0x80; // See https://github.com/little-dude/netlink/blob/0185b2952505e271805902bf175fee6ea86c42b8/netlink-packet-route/src/rtnl/constants.rs#L770
let state = if neigh.state != 0 {
neigh.state as u16
} else {
IFA_F_PERMANENT
};
let link = self.find_link(LinkFilter::Name(&neigh.device)).await?;
let message = NeighbourMessage {
header: NeighbourHeader {
family: match ip {
IpAddr::V4(_) => packet::AF_INET,
IpAddr::V6(_) => packet::AF_INET6,
} as u8,
ifindex: link.index(),
state: if neigh.state != 0 {
neigh.state as u16
} else {
IFA_F_PERMANENT
},
flags: neigh.flags as u8,
ntype: NDA_UNSPEC as u8,
},
nlas: {
let mut nlas = vec![Nla::Destination(match ip {
IpAddr::V4(v4) => v4.octets().to_vec(),
IpAddr::V6(v6) => v6.octets().to_vec(),
})];
let mut flags = Vec::new();
for flag in ALL_RULE_FLAGS {
if (neigh.flags as u8 & (u8::from(flag))) > 0 {
flags.push(flag);
}
}
if !neigh.lladdr.is_empty() {
nlas.push(Nla::LinkLocalAddress(
parse_mac_address(&neigh.lladdr)?.to_vec(),
));
}
let mut message = NeighbourMessage::default();
nlas
message.header = NeighbourHeader {
family: match ip {
IpAddr::V4(_) => AddressFamily::Inet,
IpAddr::V6(_) => AddressFamily::Inet6,
},
ifindex: link.index(),
state: NeighbourState::from(state),
flags,
kind: RouteType::from(NDA_UNSPEC as u8),
};
let mut nlas = vec![NeighbourAttribute::Destination(match ip {
IpAddr::V4(ipv4_addr) => NeighbourAddress::from(ipv4_addr),
IpAddr::V6(ipv6_addr) => NeighbourAddress::from(ipv6_addr),
})];
if !neigh.lladdr.is_empty() {
nlas.push(NeighbourAttribute::LinkLocalAddress(
parse_mac_address(&neigh.lladdr)?.to_vec(),
));
}
message.attributes = nlas;
// Send request and ACK
let mut req = NetlinkMessage::from(RtnlMessage::NewNeighbour(message));
req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_REPLACE;
req.header.flags = (NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_REPLACE) as u16;
let mut response = self.handle.request(req)?;
while let Some(message) = response.next().await {
@ -700,13 +714,13 @@ fn parse_mac_address(addr: &str) -> Result<[u8; 6]> {
}
/// Wraps external type with the local one, so we can implement various extensions and type conversions.
struct Link(packet::LinkMessage);
struct Link(LinkMessage);
impl Link {
/// If name.
fn name(&self) -> String {
use packet::nlas::link::Nla;
self.nlas
use LinkAttribute as Nla;
self.attributes
.iter()
.find_map(|n| {
if let Nla::IfName(name) = n {
@ -720,8 +734,8 @@ impl Link {
/// Extract Mac address.
fn address(&self) -> String {
use packet::nlas::link::Nla;
self.nlas
use LinkAttribute as Nla;
self.attributes
.iter()
.find_map(|n| {
if let Nla::Address(data) = n {
@ -735,7 +749,12 @@ impl Link {
/// Returns whether the link is UP
fn is_up(&self) -> bool {
self.header.flags & packet::rtnl::constants::IFF_UP > 0
let mut flags: u32 = 0;
for flag in &self.header.flags {
flags += u32::from(*flag);
}
flags as i32 & libc::IFF_UP > 0
}
fn index(&self) -> u32 {
@ -743,8 +762,8 @@ impl Link {
}
fn mtu(&self) -> Option<u64> {
use packet::nlas::link::Nla;
self.nlas.iter().find_map(|n| {
use LinkAttribute as Nla;
self.attributes.iter().find_map(|n| {
if let Nla::Mtu(mtu) = n {
Some(*mtu as u64)
} else {
@ -754,21 +773,21 @@ impl Link {
}
}
impl From<packet::LinkMessage> for Link {
fn from(msg: packet::LinkMessage) -> Self {
impl From<LinkMessage> for Link {
fn from(msg: LinkMessage) -> Self {
Link(msg)
}
}
impl Deref for Link {
type Target = packet::LinkMessage;
type Target = LinkMessage;
fn deref(&self) -> &Self::Target {
&self.0
}
}
struct Address(packet::AddressMessage);
struct Address(AddressMessage);
impl TryFrom<Address> for IPAddress {
type Error = anyhow::Error;
@ -798,7 +817,7 @@ impl TryFrom<Address> for IPAddress {
impl Address {
fn is_ipv6(&self) -> bool {
self.0.header.family == packet::constants::AF_INET6 as u8
u8::from(self.0.header.family) == libc::AF_INET6 as u8
}
#[allow(dead_code)]
@ -807,13 +826,13 @@ impl Address {
}
fn address(&self) -> String {
use packet::nlas::address::Nla;
use AddressAttribute as Nla;
self.0
.nlas
.attributes
.iter()
.find_map(|n| {
if let Nla::Address(data) = n {
format_address(data).ok()
Some(data.to_string())
} else {
None
}
@ -822,13 +841,13 @@ impl Address {
}
fn local(&self) -> String {
use packet::nlas::address::Nla;
use AddressAttribute as Nla;
self.0
.nlas
.attributes
.iter()
.find_map(|n| {
if let Nla::Local(data) = n {
format_address(data).ok()
Some(data.to_string())
} else {
None
}
@ -837,10 +856,21 @@ impl Address {
}
}
fn parse_route_addr(ra: &RouteAddress) -> Result<IpAddr> {
let ipaddr = match ra {
RouteAddress::Inet6(ipv6_addr) => ipv6_addr.to_canonical(),
RouteAddress::Inet(ipv4_addr) => IpAddr::from(*ipv4_addr),
_ => return Err(anyhow!("got invalid route address")),
};
Ok(ipaddr)
}
#[cfg(test)]
mod tests {
use super::*;
use rtnetlink::packet;
use netlink_packet_route::address::AddressHeader;
use netlink_packet_route::link::LinkHeader;
use std::iter;
use std::process::Command;
use test_utils::skip_if_not_root;
@ -853,7 +883,7 @@ mod tests {
.await
.expect("Loopback not found");
assert_ne!(message.header, packet::LinkHeader::default());
assert_ne!(message.header, LinkHeader::default());
assert_eq!(message.name(), "lo");
}
@ -928,7 +958,7 @@ mod tests {
assert_ne!(list.len(), 0);
for addr in &list {
assert_ne!(addr.0.header, packet::AddressHeader::default());
assert_ne!(addr.0.header, AddressHeader::default());
}
}
@ -952,7 +982,7 @@ mod tests {
}
#[tokio::test]
async fn add_delete_addresses() {
async fn add_update_addresses() {
skip_if_not_root!();
let list = vec![
@ -981,9 +1011,9 @@ mod tests {
assert!(result.is_some());
// Delete it
// Update it
handle
.delete_addresses(iter::once(result.unwrap()))
.add_addresses(lo.index(), iter::once(network))
.await
.expect("Failed to delete address");
}

View File

@ -58,6 +58,7 @@ message Route {
string source = 4;
uint32 scope = 5;
IPFamily family = 6;
uint32 flags = 7;
}
message ARPNeighbor {

View File

@ -9,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
dependencies = [
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -238,7 +238,7 @@ checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -316,7 +316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78d456f91b4c1fdebf2698214e599fec3d7f8b46e3140fb254a9ea88c970ab0a"
dependencies = [
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -412,7 +412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b"
dependencies = [
"libc",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -446,7 +446,7 @@ dependencies = [
"log",
"nix 0.25.1",
"regex",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -460,7 +460,7 @@ dependencies = [
"nix 0.26.2",
"serde",
"serde_json",
"thiserror",
"thiserror 1.0.44",
"tokio",
]
@ -495,7 +495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f190f3c954f7bca3c6296d0ec561c739bdbe6c7e990294ed168d415f6e1b5b01"
dependencies = [
"nix 0.27.1",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -520,7 +520,7 @@ dependencies = [
"slog",
"slog-scope",
"strum 0.24.1",
"thiserror",
"thiserror 1.0.44",
"tokio",
"ttrpc",
]
@ -571,7 +571,7 @@ dependencies = [
"serde_json",
"signal-hook",
"signal-hook-tokio",
"thiserror",
"thiserror 1.0.44",
"time 0.3.37",
"tokio",
"windows-sys 0.48.0",
@ -750,7 +750,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -772,7 +772,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core 0.20.10",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -796,7 +796,7 @@ dependencies = [
"lazy_static",
"libc",
"nix 0.23.2",
"thiserror",
"thiserror 1.0.44",
"vm-memory",
"vmm-sys-util 0.11.1",
]
@ -805,7 +805,7 @@ dependencies = [
name = "dbs-allocator"
version = "0.1.1"
dependencies = [
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -816,7 +816,7 @@ dependencies = [
"kvm-ioctls",
"libc",
"memoffset 0.6.5",
"thiserror",
"thiserror 1.0.44",
"vm-memory",
"vmm-sys-util 0.11.1",
]
@ -830,7 +830,7 @@ dependencies = [
"kvm-ioctls",
"lazy_static",
"libc",
"thiserror",
"thiserror 1.0.44",
"vm-fdt",
"vm-memory",
]
@ -839,7 +839,7 @@ dependencies = [
name = "dbs-device"
version = "0.2.0"
dependencies = [
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -881,7 +881,7 @@ dependencies = [
"kvm-ioctls",
"libc",
"log",
"thiserror",
"thiserror 1.0.44",
"vfio-bindings",
"vfio-ioctls",
"vm-memory",
@ -895,7 +895,7 @@ dependencies = [
"dbs-utils",
"dbs-virtio-devices",
"log",
"thiserror",
"thiserror 1.0.44",
"timerfd",
]
@ -908,7 +908,7 @@ dependencies = [
"libc",
"log",
"serde",
"thiserror",
"thiserror 1.0.44",
"timerfd",
"vmm-sys-util 0.11.1",
]
@ -939,7 +939,7 @@ dependencies = [
"sendfd",
"serde",
"serde_json",
"thiserror",
"thiserror 1.0.44",
"threadpool",
"timerfd",
"vhost",
@ -999,7 +999,7 @@ dependencies = [
"darling 0.20.10",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -1009,7 +1009,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b"
dependencies = [
"derive_builder_core",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -1101,7 +1101,7 @@ dependencies = [
"serde_json",
"slog",
"slog-scope",
"thiserror",
"thiserror 1.0.44",
"tracing",
"vfio-bindings",
"vfio-ioctls",
@ -1360,7 +1360,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -1716,7 +1716,7 @@ dependencies = [
"tempdir",
"test-utils",
"tests_utils",
"thiserror",
"thiserror 1.0.44",
"tokio",
"tracing",
"ttrpc",
@ -1872,7 +1872,7 @@ dependencies = [
"slog",
"slog-scope",
"subprocess",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -1895,7 +1895,7 @@ dependencies = [
"slog",
"slog-scope",
"sysinfo",
"thiserror",
"thiserror 1.0.44",
"toml 0.5.11",
]
@ -2004,9 +2004,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.19"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
dependencies = [
"value-bag",
]
@ -2131,26 +2131,25 @@ dependencies = [
[[package]]
name = "netlink-packet-core"
version = "0.4.2"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297"
checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4"
dependencies = [
"anyhow",
"byteorder",
"libc",
"netlink-packet-utils",
]
[[package]]
name = "netlink-packet-route"
version = "0.13.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5dee5ed749373c298237fe694eb0a51887f4cc1a27370c8464bac4382348f1a"
checksum = "74c171cd77b4ee8c7708da746ce392440cb7bcf618d122ec9ecc607b12938bf4"
dependencies = [
"anyhow",
"bitflags 1.3.2",
"byteorder",
"libc",
"log",
"netlink-packet-core",
"netlink-packet-utils",
]
@ -2164,21 +2163,21 @@ dependencies = [
"anyhow",
"byteorder",
"paste",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
name = "netlink-proto"
version = "0.10.0"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6"
checksum = "86b33524dc0968bfad349684447bfce6db937a9ac3332a1fe60c0c5a5ce63f21"
dependencies = [
"bytes",
"futures 0.3.28",
"log",
"netlink-packet-core",
"netlink-sys",
"thiserror",
"thiserror 1.0.44",
"tokio",
]
@ -2202,7 +2201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23541694f1d7d18cd1a0da3a1352a6ea48b01cbb4a8e7a6e547963823fd5276e"
dependencies = [
"nix 0.23.2",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -2435,7 +2434,7 @@ dependencies = [
"serde_json",
"strum 0.26.3",
"strum_macros 0.26.4",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -2473,7 +2472,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -2544,7 +2543,7 @@ dependencies = [
"opentelemetry",
"opentelemetry-http",
"opentelemetry-semantic-conventions",
"thiserror",
"thiserror 1.0.44",
"thrift",
"tokio",
]
@ -2571,7 +2570,7 @@ dependencies = [
"js-sys",
"once_cell",
"pin-project-lite",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -2591,7 +2590,7 @@ dependencies = [
"opentelemetry_api",
"percent-encoding",
"rand 0.8.5",
"thiserror",
"thiserror 1.0.44",
"tokio",
"tokio-stream",
]
@ -2755,7 +2754,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -2840,9 +2839,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.75"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
@ -2889,7 +2888,7 @@ dependencies = [
"parking_lot 0.12.1",
"procfs 0.14.2",
"protobuf 2.28.0",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -2957,7 +2956,7 @@ checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e"
dependencies = [
"once_cell",
"protobuf-support",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -2981,7 +2980,7 @@ dependencies = [
"protobuf-parse",
"regex",
"tempfile",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -2996,7 +2995,7 @@ dependencies = [
"protobuf 3.2.0",
"protobuf-support",
"tempfile",
"thiserror",
"thiserror 1.0.44",
"which",
]
@ -3006,7 +3005,7 @@ version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372"
dependencies = [
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -3254,7 +3253,7 @@ checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom 0.2.10",
"redox_syscall 0.2.16",
"thiserror",
"thiserror 1.0.44",
]
[[package]]
@ -3382,16 +3381,19 @@ dependencies = [
[[package]]
name = "rtnetlink"
version = "0.11.0"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f1cfa18f8cebe685373a2697915d7e0db3b4554918bba118385e0f71f258a7"
checksum = "b684475344d8df1859ddb2d395dd3dac4f8f3422a1aa0725993cb375fc5caba5"
dependencies = [
"futures 0.3.28",
"log",
"netlink-packet-core",
"netlink-packet-route",
"netlink-packet-utils",
"netlink-proto",
"nix 0.24.3",
"thiserror",
"netlink-sys",
"nix 0.27.1",
"thiserror 1.0.44",
"tokio",
]
@ -3642,7 +3644,7 @@ checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -3712,7 +3714,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -3807,7 +3809,7 @@ dependencies = [
"slog-stdlog",
"tempfile",
"tests_utils",
"thiserror",
"thiserror 1.0.44",
"tokio",
"tracing",
"tracing-opentelemetry",
@ -4019,7 +4021,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -4051,9 +4053,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.48"
version = "2.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
dependencies = [
"proc-macro2",
"quote",
@ -4148,7 +4150,16 @@ version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
dependencies = [
"thiserror-impl",
"thiserror-impl 1.0.44",
]
[[package]]
name = "thiserror"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
dependencies = [
"thiserror-impl 2.0.11",
]
[[package]]
@ -4159,7 +4170,18 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
name = "thiserror-impl"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.96",
]
[[package]]
@ -4289,7 +4311,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -4384,7 +4406,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
]
[[package]]
@ -4458,7 +4480,7 @@ dependencies = [
"nix 0.26.2",
"protobuf 3.2.0",
"protobuf-codegen 3.2.0",
"thiserror",
"thiserror 1.0.44",
"tokio",
"tokio-vsock",
"windows-sys 0.48.0",
@ -4567,9 +4589,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "value-bag"
version = "1.4.1"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3"
checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2"
[[package]]
name = "vcpkg"
@ -4600,7 +4622,7 @@ dependencies = [
"kvm-ioctls",
"libc",
"log",
"thiserror",
"thiserror 2.0.11",
"vfio-bindings",
"vm-memory",
"vmm-sys-util 0.11.1",
@ -4780,7 +4802,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
"wasm-bindgen-shared",
]
@ -4814,7 +4836,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.96",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]

View File

@ -228,6 +228,7 @@ impl From<Route> for types::Route {
source: from.source,
scope: from.scope,
family: protobuf::EnumOrUnknown::new(from.family.into()),
flags: from.flags,
..Default::default()
}
}
@ -242,6 +243,7 @@ impl From<types::Route> for Route {
source: src.source,
scope: src.scope,
family: src.family.unwrap().into(),
flags: src.flags,
}
}
}

View File

@ -113,6 +113,7 @@ pub struct Route {
pub source: String,
pub scope: u32,
pub family: IPFamily,
pub flags: u32,
}
#[derive(Deserialize, Debug, PartialEq, Clone, Default)]

View File

@ -21,10 +21,10 @@ lazy_static = "1.4.0"
libc = ">=0.2.39"
netns-rs = "0.1.0"
netlink-sys = "0.8.3"
netlink-packet-route = "0.13.0"
netlink-packet-route = "0.19.0"
nix = "0.24.2"
rand = "^0.7.2"
rtnetlink = "0.11.0"
rtnetlink = "0.14.0"
scopeguard = "1.0.0"
serde = { version = "1.0.138", features = ["derive"] }
serde_json = "1.0.82"

View File

@ -290,6 +290,8 @@ pub(crate) struct Route {
// Scope
#[serde(default)]
pub scope: u32,
#[serde(default)]
pub flags: u32,
}
impl Route {
@ -399,6 +401,7 @@ mod tests {
source: "172.18.0.1".to_owned(),
gateway: "172.18.31.1".to_owned(),
scope: 0,
flags: 0,
}],
neighbors: vec![ARPNeighbor {
ip_address: Some("192.168.0.3/16".to_owned()),

View File

@ -10,7 +10,6 @@ mod tests {
use anyhow::{anyhow, Context, Result};
use kata_types::config::hypervisor::TopologyConfigInfo;
use netlink_packet_route::MACVLAN_MODE_PRIVATE;
use scopeguard::defer;
use tests_utils::load_test_config;
use tokio::sync::RwLock;
@ -200,6 +199,9 @@ mod tests {
.await
.expect("failed to get the index of dummy link");
// Available MACVLAN MODES
let macvlan_mode_private: u32 = 1;
// the mode here does not matter, could be any of available modes
if let Ok(()) = handle
.link()
@ -207,7 +209,7 @@ mod tests {
.macvlan(
manual_macvlan_iface_name.clone(),
dummy_index,
MACVLAN_MODE_PRIVATE,
macvlan_mode_private,
)
.execute()
.await

View File

@ -7,7 +7,7 @@
use agent::{ARPNeighbor, IPAddress, Interface, Route};
use anyhow::Result;
use async_trait::async_trait;
use netlink_packet_route::IFF_NOARP;
use netlink_packet_route::link::LinkFlag::Noarp;
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 & IFF_NOARP,
raw_flags: dan_device.network_info.interface.flags & u32::from(Noarp),
};
let routes = dan_device
@ -74,6 +74,7 @@ impl NetworkInfoFromDan {
source: route.source.clone(),
scope: route.scope,
family,
flags: route.flags,
})
})
.collect();
@ -159,6 +160,7 @@ mod tests {
source: "172.18.0.1".to_owned(),
gateway: "172.18.31.1".to_owned(),
scope: 0,
flags: 0,
}],
neighbors: vec![DanARPNeighbor {
ip_address: Some("192.168.0.3/16".to_owned()),
@ -194,6 +196,7 @@ mod tests {
source: "172.18.0.1".to_owned(),
scope: 0,
family: IPFamily::V4,
flags: 0,
}];
assert_eq!(routes, network_info.routes().await.unwrap());

View File

@ -4,19 +4,21 @@
// SPDX-License-Identifier: Apache-2.0
//
use std::convert::TryFrom;
use std::{convert::TryFrom, net::IpAddr};
use agent::{ARPNeighbor, IPAddress, IPFamily, Interface, Route};
use anyhow::{Context, Result};
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use futures::stream::TryStreamExt;
use netlink_packet_route::{
self, neighbour::NeighbourMessage, nlas::neighbour::Nla, route::RouteMessage,
self,
neighbour::{NeighbourAddress, NeighbourAttribute, NeighbourMessage},
route::{RouteAddress, RouteAttribute, RouteMessage},
};
use super::NetworkInfo;
use crate::network::utils::{
address::{parse_ip, Address},
address::Address,
link::{self, LinkAttrs},
};
@ -74,7 +76,7 @@ pub async fn handle_addresses(
.await
.context("try next address msg")?
{
let family = addr_msg.header.family as i32;
let family = u8::from(addr_msg.header.family) as i32;
if family != libc::AF_INET && family != libc::AF_INET6 {
warn!(sl!(), "unsupported ip family {}", family);
continue;
@ -100,13 +102,17 @@ pub async fn handle_addresses(
fn generate_neigh(name: &str, n: &NeighbourMessage) -> Result<ARPNeighbor> {
let mut neigh = ARPNeighbor {
device: name.to_string(),
state: n.header.state as i32,
state: u16::from(n.header.state) as i32,
..Default::default()
};
for nla in &n.nlas {
for nla in &n.attributes {
match nla {
Nla::Destination(addr) => {
let dest = parse_ip(addr, n.header.family).context("parse ip")?;
NeighbourAttribute::Destination(addr) => {
let dest = match addr {
NeighbourAddress::Inet6(ipv6_addr) => ipv6_addr.to_canonical(),
NeighbourAddress::Inet(ipv4_addr) => IpAddr::from(*ipv4_addr),
_ => return Err(anyhow!("invalid address")),
};
let addr = Some(IPAddress {
family: if dest.is_ipv4() {
IPFamily::V4
@ -118,7 +124,7 @@ fn generate_neigh(name: &str, n: &NeighbourMessage) -> Result<ARPNeighbor> {
});
neigh.to_ip_address = addr;
}
Nla::LinkLocalAddress(addr) => {
NeighbourAttribute::LinkLocalAddress(addr) => {
if addr.len() < 6 {
continue;
}
@ -157,29 +163,49 @@ async fn handle_neighbors(
Ok(neighs)
}
fn generate_route(name: &str, route: &RouteMessage) -> Result<Option<Route>> {
if route.header.protocol == libc::RTPROT_KERNEL {
fn generate_route(name: &str, route_msg: &RouteMessage) -> Result<Option<Route>> {
if u8::from(route_msg.header.protocol) == libc::RTPROT_KERNEL {
return Ok(None);
}
Ok(Some(Route {
dest: route
.destination_prefix()
.map(|(addr, prefix)| format!("{}/{}", addr, prefix))
.unwrap_or_default(),
gateway: route.gateway().map(|v| v.to_string()).unwrap_or_default(),
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(),
source: route
.source_prefix()
.map(|(addr, _)| addr.to_string())
.unwrap_or_default(),
scope: route.header.scope as u32,
family: if route.header.address_family == libc::AF_INET as u8 {
family: if u8::from(route_msg.header.address_family) == libc::AF_INET as u8 {
IPFamily::V4
} else {
IPFamily::V6
},
}))
flags,
..Default::default()
};
for nla in &route_msg.attributes {
match nla {
RouteAttribute::Destination(d) => {
let dest = parse_route_addr(d)?;
route.dest = dest.to_string();
}
RouteAttribute::Gateway(g) => {
let dest = parse_route_addr(g)?;
route.gateway = dest.to_string();
}
RouteAttribute::Source(s) => {
let dest = parse_route_addr(s)?;
route.source = dest.to_string();
}
_ => {}
}
}
Ok(Some(route))
}
async fn get_route_from_msg(
@ -190,12 +216,16 @@ async fn get_route_from_msg(
) -> Result<()> {
let name = &attrs.name;
let mut route_msg_list = handle.route().get(ip_version).execute();
while let Some(route) = route_msg_list.try_next().await? {
while let Some(route_msg) = route_msg_list.try_next().await? {
// get route filter with index
if let Some(index) = route.output_interface() {
if index == attrs.index {
if let Some(route) = generate_route(name, &route).context("generate route")? {
routes.push(route);
for attr in &route_msg.attributes {
if let RouteAttribute::Oif(index) = attr {
if *index == attrs.index {
if let Some(route) =
generate_route(name, &route_msg).context("generate route")?
{
routes.push(route);
}
}
}
}
@ -228,3 +258,13 @@ impl NetworkInfo for NetworkInfoFromLink {
Ok(self.neighs.clone())
}
}
fn parse_route_addr(ra: &RouteAddress) -> Result<IpAddr> {
let ipaddr = match ra {
RouteAddress::Inet6(ipv6_addr) => ipv6_addr.to_canonical(),
RouteAddress::Inet(ipv4_addr) => IpAddr::from(*ipv4_addr),
_ => return Err(anyhow!("got invalid route address")),
};
Ok(ipaddr)
}

View File

@ -64,7 +64,7 @@ impl NetworkModel for TcFilterModel {
.parent(0xffff0000)
// get protocol with network byte order
.protocol(0x0003_u16.to_be())
.redirect(virt_index)
.redirect(virt_index)?
.execute()
.await
.context("add redirect for tap")?;
@ -75,7 +75,7 @@ impl NetworkModel for TcFilterModel {
.parent(0xffff0000)
// get protocol with network byte order
.protocol(0x0003_u16.to_be())
.redirect(tap_index)
.redirect(tap_index)?
.execute()
.await
.context("add redirect for virt")?;

View File

@ -157,7 +157,7 @@ pub async fn create_link(
handle
.link()
.set(base.index)
.master(base.master_index)
.controller(base.master_index)
.execute()
.await
.context("set index")?;

View File

@ -5,13 +5,13 @@
//
use std::convert::TryFrom;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::net::{IpAddr, Ipv4Addr};
use std::str::FromStr;
use agent::IPFamily;
use anyhow::{anyhow, Context, Result};
use netlink_packet_route::nlas::address::Nla;
use netlink_packet_route::{AddressMessage, AF_INET, AF_INET6};
use netlink_packet_route::address::AddressAttribute;
use netlink_packet_route::address::AddressMessage;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Address {
@ -29,34 +29,42 @@ pub struct Address {
impl TryFrom<AddressMessage> for Address {
type Error = anyhow::Error;
fn try_from(msg: AddressMessage) -> Result<Self> {
let AddressMessage { header, nlas } = msg;
let AddressMessage {
header, attributes, ..
} = msg;
let mut addr = Address {
addr: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
peer: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
broadcast: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
label: String::default(),
flags: 0,
scope: header.scope,
scope: u8::from(header.scope),
perfix_len: header.prefix_len,
prefered_lft: 0,
valid_ltf: 0,
};
for nla in nlas.into_iter() {
for nla in attributes.into_iter() {
match nla {
Nla::Address(a) => {
addr.addr = parse_ip(&a, header.family)?;
AddressAttribute::Address(a) => {
addr.addr = a;
}
Nla::Broadcast(b) => {
addr.broadcast = parse_ip(&b, header.family)?;
AddressAttribute::Broadcast(b) => {
addr.broadcast = IpAddr::V4(b);
}
Nla::Label(l) => {
AddressAttribute::Label(l) => {
addr.label = l;
}
Nla::Flags(f) => {
addr.flags = f;
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;
}
Nla::CacheInfo(_c) => {}
AddressAttribute::CacheInfo(_c) => {}
_ => {}
}
}
@ -65,26 +73,6 @@ impl TryFrom<AddressMessage> for Address {
}
}
pub(crate) fn parse_ip(ip: &[u8], family: u8) -> Result<IpAddr> {
let support_len = if family as u16 == AF_INET { 4 } else { 16 };
if ip.len() != support_len {
return Err(anyhow!(
"invalid ip addresses {:?} support {}",
&ip,
support_len
));
}
match family as u16 {
AF_INET => Ok(IpAddr::V4(Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]))),
AF_INET6 => {
let mut octets = [0u8; 16];
octets.copy_from_slice(&ip[..16]);
Ok(IpAddr::V6(Ipv6Addr::from(octets)))
}
_ => Err(anyhow!("unknown IP network family {}", family)),
}
}
pub(crate) fn parse_ip_cidr(ip: &str) -> Result<(IpAddr, u8)> {
let items: Vec<&str> = ip.split('/').collect();
if items.len() != 2 {
@ -124,28 +112,6 @@ pub(crate) fn ip_family_from_ip_addr(ip_addr: &IpAddr) -> IPFamily {
mod tests {
use super::*;
#[test]
fn test_parse_ip() {
let test_ipv4 = [10, 25, 64, 128];
let ipv4 = parse_ip(test_ipv4.as_slice(), AF_INET as u8).unwrap();
let expected_ipv4 = IpAddr::V4(Ipv4Addr::new(10, 25, 64, 128));
assert_eq!(ipv4, expected_ipv4);
let test_ipv6 = [0, 2, 4, 0, 0, 2, 4, 0, 0, 2, 4, 0, 0, 2, 4, 0];
let ipv6 = parse_ip(test_ipv6.as_slice(), AF_INET6 as u8).unwrap();
// two u8 => one u16, (0u8, 2u8 => 0x0002), (4u8, 0u8 => 0x0400)
let expected_ipv6 = IpAddr::V6(Ipv6Addr::new(
0x0002, 0x0400, 0x0002, 0x0400, 0x0002, 0x0400, 0x0002, 0x0400,
));
assert_eq!(ipv6, expected_ipv6);
let fail_ipv4 = [10, 22, 33, 44, 55];
assert!(parse_ip(fail_ipv4.as_slice(), AF_INET as u8).is_err());
let fail_ipv6 = [1, 2, 3, 4, 5, 6, 7, 8, 2, 3];
assert!(parse_ip(fail_ipv6.as_slice(), AF_INET6 as u8).is_err());
}
#[test]
fn test_parse_ip_cidr() {
let test_cases = [

View File

@ -4,73 +4,84 @@
// SPDX-License-Identifier: Apache-2.0
//
use netlink_packet_route::{
link::nlas::{Info, InfoBridge, InfoData, InfoKind, Nla},
LinkMessage,
use netlink_packet_route::link::{
InfoBridge, InfoData, InfoKind, LinkAttribute, LinkFlag, LinkInfo, LinkMessage,
};
use super::{Link, LinkAttrs};
pub(crate) struct VecLinkFlag(pub Vec<LinkFlag>);
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<dyn Link> {
let flags = u32::from(&VecLinkFlag(msg.header.flags));
let mut base = LinkAttrs {
index: msg.header.index,
flags: msg.header.flags,
link_layer_type: msg.header.link_layer_type,
flags,
link_layer_type: u16::from(msg.header.link_layer_type),
..Default::default()
};
if msg.header.flags & libc::IFF_PROMISC as u32 != 0 {
if flags & libc::IFF_PROMISC as u32 != 0 {
base.promisc = 1;
}
let mut link: Option<Box<dyn Link>> = None;
while let Some(attr) = msg.nlas.pop() {
while let Some(attr) = msg.attributes.pop() {
match attr {
Nla::Info(infos) => {
LinkAttribute::LinkInfo(infos) => {
link = Some(link_info(infos));
}
Nla::Address(a) => {
LinkAttribute::Address(a) => {
base.hardware_addr = a;
}
Nla::IfName(i) => {
LinkAttribute::IfName(i) => {
base.name = i;
}
Nla::Mtu(m) => {
LinkAttribute::Mtu(m) => {
base.mtu = m;
}
Nla::Link(l) => {
LinkAttribute::Link(l) => {
base.parent_index = l;
}
Nla::Master(m) => {
LinkAttribute::Controller(m) => {
base.master_index = m;
}
Nla::TxQueueLen(t) => {
LinkAttribute::TxQueueLen(t) => {
base.txq_len = t;
}
Nla::IfAlias(a) => {
LinkAttribute::IfAlias(a) => {
base.alias = a;
}
Nla::Stats(_s) => {}
Nla::Stats64(_s) => {}
Nla::Xdp(_x) => {}
Nla::ProtoInfo(_) => {}
Nla::OperState(_) => {}
Nla::NetnsId(n) => {
LinkAttribute::Stats(_s) => {}
LinkAttribute::Stats64(_s) => {}
LinkAttribute::Xdp(_x) => {}
LinkAttribute::OperState(_) => {}
LinkAttribute::NetnsId(n) => {
base.net_ns_id = n;
}
Nla::GsoMaxSize(i) => {
LinkAttribute::GsoMaxSize(i) => {
base.gso_max_size = i;
}
Nla::GsoMaxSegs(e) => {
LinkAttribute::GsoMaxSegs(e) => {
base.gso_max_seqs = e;
}
Nla::VfInfoList(_) => {}
Nla::NumTxQueues(t) => {
LinkAttribute::VfInfoList(_) => {}
LinkAttribute::NumTxQueues(t) => {
base.num_tx_queues = t;
}
Nla::NumRxQueues(r) => {
LinkAttribute::NumRxQueues(r) => {
base.num_rx_queues = r;
}
Nla::Group(g) => {
LinkAttribute::Group(g) => {
base.group = g;
}
_ => {
@ -85,11 +96,11 @@ pub fn get_link_from_message(mut msg: LinkMessage) -> Box<dyn Link> {
}
#[allow(clippy::box_default)]
fn link_info(mut infos: Vec<Info>) -> Box<dyn Link> {
fn link_info(mut infos: Vec<LinkInfo>) -> Box<dyn Link> {
let mut link: Option<Box<dyn Link>> = None;
while let Some(info) = infos.pop() {
match info {
Info::Kind(kind) => match kind {
LinkInfo::Kind(kind) => match kind {
InfoKind::Tun => {
if link.is_none() {
link = Some(Box::new(Tuntap::default()));
@ -126,7 +137,7 @@ fn link_info(mut infos: Vec<Info>) -> Box<dyn Link> {
}
}
},
Info::Data(data) => match data {
LinkInfo::Data(data) => match data {
InfoData::Tun(_) => {
link = Some(Box::new(Tuntap::default()));
}
@ -149,12 +160,12 @@ fn link_info(mut infos: Vec<Info>) -> Box<dyn Link> {
link = Some(Box::new(Device::default()));
}
},
Info::SlaveKind(_sk) => {
LinkInfo::PortKind(_sk) => {
if link.is_none() {
link = Some(Box::new(Device::default()));
}
}
Info::SlaveData(_sd) => {
LinkInfo::PortData(_sd) => {
link = Some(Box::new(Device::default()));
}
_ => {

View File

@ -14,7 +14,7 @@ pub use manager::get_link_from_message;
use std::os::unix::io::RawFd;
use netlink_packet_route::link::nlas::State;
use netlink_packet_route::link::State;
#[cfg(test)]
pub use create::net_test_utils;

View File

@ -309,6 +309,7 @@ func generateVCNetworkStructures(ctx context.Context, endpoints []Endpoint) ([]*
r.Device = endpoint.Name()
r.Scope = uint32(route.Scope)
r.Family = utils.ConvertAddressFamily((int32)(route.Family))
r.Flags = uint32(route.Flags)
routes = append(routes, &r)
}

View File

@ -7,8 +7,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.21.12
// protoc-gen-go v1.32.0
// protoc v5.29.3
// source: types.proto
package protocols
@ -307,6 +307,7 @@ type Route struct {
Source string `protobuf:"bytes,4,opt,name=source,proto3" json:"source,omitempty"`
Scope uint32 `protobuf:"varint,5,opt,name=scope,proto3" json:"scope,omitempty"`
Family IPFamily `protobuf:"varint,6,opt,name=family,proto3,enum=types.IPFamily" json:"family,omitempty"`
Flags uint32 `protobuf:"varint,7,opt,name=flags,proto3" json:"flags,omitempty"`
}
func (x *Route) Reset() {
@ -383,6 +384,13 @@ func (x *Route) GetFamily() IPFamily {
return IPFamily_v4
}
func (x *Route) GetFlags() uint32 {
if x != nil {
return x.Flags
}
return 0
}
type ARPNeighbor struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -486,7 +494,7 @@ var file_types_proto_rawDesc = []byte{
0x09, 0x52, 0x07, 0x70, 0x63, 0x69, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79,
0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b,
0x0a, 0x09, 0x72, 0x61, 0x77, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x08, 0x72, 0x61, 0x77, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0xa4, 0x01, 0x0a, 0x05,
0x0d, 0x52, 0x08, 0x72, 0x61, 0x77, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0xba, 0x01, 0x0a, 0x05,
0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x61, 0x74,
0x65, 0x77, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x61, 0x74, 0x65,
@ -497,28 +505,29 @@ var file_types_proto_rawDesc = []byte{
0x28, 0x0d, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x66, 0x61, 0x6d,
0x69, 0x6c, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65,
0x73, 0x2e, 0x49, 0x50, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69,
0x6c, 0x79, 0x22, 0x9d, 0x01, 0x0a, 0x0b, 0x41, 0x52, 0x50, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62,
0x6f, 0x72, 0x12, 0x32, 0x0a, 0x0b, 0x74, 0x6f, 0x49, 0x50, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e,
0x49, 0x50, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0b, 0x74, 0x6f, 0x49, 0x50, 0x41,
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x16,
0x0a, 0x06, 0x6c, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x6c, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x66, 0x6c, 0x61,
0x67, 0x73, 0x2a, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x06,
0x0a, 0x02, 0x76, 0x34, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x76, 0x36, 0x10, 0x01, 0x2a, 0x35,
0x0a, 0x13, 0x46, 0x53, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50,
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10,
0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4f, 0x6e, 0x52, 0x6f, 0x6f, 0x74, 0x4d, 0x69, 0x73, 0x6d, 0x61,
0x74, 0x63, 0x68, 0x10, 0x01, 0x42, 0x5b, 0x5a, 0x59, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x74, 0x61, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x65, 0x72, 0x73, 0x2f, 0x6b, 0x61, 0x74, 0x61, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x65, 0x72, 0x73, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2f,
0x76, 0x69, 0x72, 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2f, 0x70,
0x6b, 0x67, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x6c, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x9d, 0x01, 0x0a, 0x0b, 0x41, 0x52, 0x50,
0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x12, 0x32, 0x0a, 0x0b, 0x74, 0x6f, 0x49, 0x50,
0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e,
0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x50, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52,
0x0b, 0x74, 0x6f, 0x49, 0x50, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06,
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65,
0x76, 0x69, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x12, 0x14, 0x0a, 0x05,
0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61,
0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
0x05, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x2a, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x46, 0x61,
0x6d, 0x69, 0x6c, 0x79, 0x12, 0x06, 0x0a, 0x02, 0x76, 0x34, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02,
0x76, 0x36, 0x10, 0x01, 0x2a, 0x35, 0x0a, 0x13, 0x46, 0x53, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43,
0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x41,
0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4f, 0x6e, 0x52, 0x6f, 0x6f,
0x74, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x01, 0x42, 0x5b, 0x5a, 0x59, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x74, 0x61, 0x2d, 0x63,
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2f, 0x6b, 0x61, 0x74, 0x61, 0x2d, 0x63,
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x72, 0x75,
0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x76, 0x69, 0x72, 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
0x6e, 0x65, 0x72, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (