mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-05-07 16:07:37 +00:00
Merge pull request #10760 from lifupan/route_flags_suport
This commit is contained in:
commit
0671252466
src
agent
libs/protocols/protos
runtime-rs
Cargo.lock
crates
runtime/virtcontainers
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ message Route {
|
||||
string source = 4;
|
||||
uint32 scope = 5;
|
||||
IPFamily family = 6;
|
||||
uint32 flags = 7;
|
||||
}
|
||||
|
||||
message ARPNeighbor {
|
||||
|
170
src/runtime-rs/Cargo.lock
generated
170
src/runtime-rs/Cargo.lock
generated
@ -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",
|
||||
]
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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"
|
||||
|
@ -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()),
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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")?;
|
||||
|
@ -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")?;
|
||||
|
@ -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 = [
|
||||
|
@ -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()));
|
||||
}
|
||||
_ => {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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 (
|
||||
|
Loading…
Reference in New Issue
Block a user